Let’s talk about anti virus detection: Kaspersky DNS cache detection

I’ve been playing around with some basic HTTP programs lately and noticed that Kaspersky flags them as viruses for some reason. I did some investigation and learned why and how to get around those detections.

I wanted to download a Web page in a program I’m writing for Windows. Windows provides some APIs to do this, like WinHttpConnect, WinHttpOpen, etc. Great, shouldn’t be an issue, right?

I copied some sample code from Microsoft to do a GET request and changed it to fit my needs. Awesome, this is super simple! However, Kaspersky flags my program as potentially malicious for using the DNS cache.

Now, it is beyond me how Kaspersky detects what is essentially sample code as malicious. And for doing DNS? Maybe if I’m hitting known malware websites, but I was hitting google.com. Any ways, that’s besides the point, so let’s move on with our lives and fix this AV detection, shall we?

Now, since we’re getting flagged for using the DNS cache, is there a way to get around that? After some MSN sifting, turns out there is! A function called DnsQuery() (duh…) can execute DNS requests for us. More importantly, there is a flag to bypass the DNS cache. So its a matter of using this call, bypassing the DNS cache, then simply passing raw IP addresses to other system calls (like WinHttpConnect).

Voila, no more AV detection! Some source code is below. If you have anymore tips or advice about AV avoidance, please leave a comment!

Notes: I was unable to get the codes to trigger on Windows 7, only on Windows XP, which is weird. I was using a trial version of Kaspersky PURE, so it might have been related to something specific about the signatures and algorithms used for those specific version? Not sure.

TL;DR: If Kaspersky flags your application as malicious for using the DNS cache, using DnsQuery() and the bypass cache option for your DNS queries, should be a good way to get around it.

Original Code:

// Specify an HTTP server.
WCHAR host[] = L"www.google.com";
if (hSession)
hConnect = WinHttpConnect( hSession, host, INTERNET_DEFAULT_HTTP_PORT, 0);

No DNS Cache Code:

DNS_STATUS status;
PDNS_RECORD pDnsRecord;
PIP4_ARRAY pSrvList = NULL;
WORD wType = DNS_TYPE_A;
char* pOwnerName;
char pReversedIP[255];
char DnsServIp[255];
DNS_FREE_TYPE freetype;
freetype = DnsFreeRecordListDeep;
IN_ADDR ipaddr;
WCHAR unicodeIpAddr[50];

ZeroMemory(unicodeIpAddr,50);

// Calling function DnsQuery to query Host or PTR records
status = DnsQuery(pOwnerName,
wType,
DNS_QUERY_BYPASS_CACHE,
pSrvList,
&pDnsRecord,
NULL);

if (status){
if(wType == DNS_TYPE_A)
printf("Failed to query the host record for %s and the error is %d \n", pOwnerName, status);
else
printf("Failed to query the PTR record and the error is %d \n", status);
} else {
if(wType == DNS_TYPE_A) {
//convert the Internet network address into a string
//in Internet standard dotted format.
ipaddr.S_un.S_addr = (pDnsRecord->Data.A.IpAddress);
printf("The IP address of the host %s is %s \n", pOwnerName,inet_ntoa(ipaddr));

// Convert to Unicode
mbstowcs(unicodeIpAddr, inet_ntoa(ipaddr), 50);

// Free memory allocated for DNS records.
DnsRecordListFree(pDnsRecord, freetype);
}
else {
printf("The host name is %s \n",(pDnsRecord->Data.PTR.pNameHost));

// Free memory allocated for DNS records.
DnsRecordListFree(pDnsRecord, freetype);
}
}
LocalFree(pSrvList);

// Now do the HTTP connect with a raw IP address instead of a host name
if (hSession)
hConnect = WinHttpConnect( hSession, unicodeIpAddr, INTERNET_DEFAULT_HTTP_PORT, 0);

About samkerr

I'm an eclectic person. I like to dabble in a multitude of things. I'm sure you'll find my blog reflects that.
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *