Some Windows APIs cause crash and Usage issues summary (AV failure of the API, can be processed with try catch capture)

Source: Internet
Author: User
Tags readfile try catch

Tag: Convert fill null negative number DDR mobile device Reg class Load

RegQueryValueEx

Gethostbyname/getaddrinfo

_localtime64

Findfirstfile/findnextfile

VerQueryValue

CreateFileMapping related

Setdlldirectory

Is there a problem with Windows API and no bugs? The answer is NO! The code is written out, how can it be completely free of problems? Let's take a look at what Windows APIs are currently found to be problematic, or use the pitfalls above.

1, RegQueryValueEx

First look at this API, get the information in the registry, the API itself is not a problem, and temporarily did not see the crash in this API. But the use of this API has some tips to keep in mind. Improper use can cause some unexpected problems or even crashes (please refer to MSDN for specific use of the API, not to repeat below).

The problem mainly occurs when we get the string value inside the registry, and look at a piece of code like this:

DWORD dwtype = REG_SZ;

DWORD dwcbdata = 0;

LONG Lret =::regqueryvalueexw (HKey, L "Installtimetest", NULL, &dwtype, NULL, &dwcbdata);

if (error_success = = Lret

&& REG_SZ = = dwtype)

{

Pbyte pbuffer = new Byte[dwcbdata];

In general, when enumerating the registry, we use code like this to detect how much storage space a registry key requires, then allocate space, and then read it, usually without a problem.

But look at one of those things. To set up the registry:

DWORD dwtype = REG_SZ;

wchar_t Szinstaltime[5] = {l ' 1 ', l ' 2 ', l ' 3 ', l ' 4 ', L ' 5 '};

DWORD dwcbdata = sizeof (szinstaltime); Number of bytes

LONG Lret =::regsetvalueexw (HKey, L "Installtimetest", NULL, dwtype, Lpbyte (szinstaltime), dwcbdata);

if (error_success = = Lret)

{

BRet = true;

}

Wonderful, yes, it sets a string into the registry, the total length of the string is 5, the number of bytes is 10 bytes (wide characters, not including the end of the 0), the length passed to RegSetValueEx is also 10, the function succeeds, it seems to have successfully written, but look at the registry inside the situation:

There is no end of the 0, at this time we use the above way to read, it will first tell you need 10 bytes of space, you allocate 10 bytes, and then read it will read a string not ending with 0 into your buffer, then you do the string of the buffer of various operations, read and write, Calculate length and so on, what happens I don't need to say more.

Some people may say that Microsoft does not say that when using RegSetValueEx, if the string is set, the length of the incoming to include the end of the 0? is not RegSetValueEx use wrong, yes, you are not wrong, but the problem is that the use of the method is also possible, do not rule out someone malicious to make your program crashes, if a security software easily crash ... There is no kind of outlook on life is completely destroyed dare feet.

OK, say back, or see how we should deal with this anomaly, actually know the reason I think the method is very simple, that is, each time the allocation, allocate some memory (wide character to allocate more than 2 bytes, for the multiline string will be more than 4 bytes allocated, because it is the end of two 0). Another way to use this is if you probably know how much space you need, and you don't really care about the data. You can also resolve this problem by allocating a certain byte of space (for example, N bytes) ahead of time, and then passing in the size of the space when you call REGQUERYVALUEEXW. N-2 or N-4 bytes.

2, Gethostbyname/getaddrinfo

In the Hosts file contains some special structure of the data, these two APIs have been proven to be crash, in fact, because there is a call in it does not empty the pointer to call Wcslen to calculate the length, you can use Disassembly Mswsock module to study the problem. And the solution is also very straightforward, that is, directly write a proxy function of such an API, and then capture the crash, the exception when the direct return to failure, because this is a simple AV exception, so after the capture will not cause other problems, is a secure capture.

The proxy function can be written like this:

struct Hostent FAR * PASCAL far gethostbyname_safe (in const char FAR * name)

{

if (NULL = = name)

return NULL;

__try

{

Return:: gethostbyname (name);

}

__except (getexceptioncode () = = Exception_access_violation? Exception_execute_handler:exception_continue_search)

{

return NULL;

}

}

As for the Getaddrinfo function, you can do the same.

3, _localtime64

This is not an API, but Microsoft's extended CRT function, which is used to put a time_t time conversion cost time and into the TM structure. In use, it is found that if an incorrect value is passed to it, crash is raised. The first Blu-ray brother reported the problem with this function (in fact, this function is similar to _LOCALTIME32, and the other function is _localtime, this function is in the compilation period according to whether the macro defined _use_32bit_time_t to call _ Localtime32 or call _localtime64).

You can try to pass these functions into the 0-like exception data (negative numbers, super-large number, 64-bit version over after 23:59:59, December 31, 3000) Try ...

In fact, Microsoft also know this problem, on MSDN have such a paragraph (later think of Microsoft also kinda pit):

These functions validate their parameters. If timer is a null pointer, or if the timer value was negative, these functions invoke an invalid parameter handler, as Des Cribed in Parameter Validation. If execution is allowed to continue, the functions return NULL and set errno to EINVAL.

It is recommended to use _set_invalid_parameter_handler to set the error parameter exception handler function, but unfortunately, this method also has a loophole, although it can catch this error, but when the system abused this method, For example, multiple modules call this function to set their own error-handling functions, this method becomes very unreliable. For example, Module 1 calls the _set_invalid_parameter_handler, then Module 2 calls the _set_invalid_parameter_handler, after a period of time Module 2 unloaded, the error handling function also points to Module 2 inside , if the module 1 again a parameter error will result in the execution of an illegal address of the error handler, the problem is more serious, module 2 before unloading the error handling function recovery? But what if there's a module 3? How to ensure that the recovery of the error handling function pointers is completely reliable? Overall, this method is not reliable and is not recommended for use.

A better solution is to _localtime series functions in accordance with their own needs, the first to help them check the parameters, and then passed to the real _localtime function processing to circumvent this problem. You can refer to the following method of detection of this function (you can fully implement this function according to your own requirements).

Inline time_t fixuptime64range (const time_t time)

{

time_t tmp_time = time;

if (Tmp_time < 0 | | Underflow

Tmp_time > (_MAX__TIME64_T-14 *)//Overflow

{

Tmp_time = 0; Reset Time to 0

}

return tmp_time;

}

/* Number of seconds from00:00:00, 01/01/1970 UTC to 23:59:59. 12/31/3000 UTC */

#define _MAX__TIME64_T 0x793406fffi64

14 * 60 * 60 for control range, the earliest time zone is utc+14 (http://zh.wikipedia.org/zh-hant/UTC%2B14)

4, Findfirstfile/findnextfile

These two combination API most people have used it, used to enumerate files and folders, general use is difficult to find problems, but in the security field, for file scanning, because the time is generally longer, it is easy to scan the target folder or disk inside the file is deleted, At this point, these two APIs are easy to crash, in practice, take place in FindNextFile more, you can use the following methods to circumvent (encapsulate a safefindnextfile function, FindFirstFile can be similar). If this is a more important logic, after these two APIs have crash, it is recommended that you reset the logic (for example, if you are scanning the virus, you can save the initial state and then restart the scan).

BOOL bRet = FALSE;

__try

{

BRet = FindNextFile (hFindFile, lpfindfiledata);

}

__except (Exception_execute_handler)

{

}

return bRet;

5, VerQueryValue

This API crash, I believe there must be a lot of people have encountered, this function is usually used to get from the file version of the resources of some similar to the file version of the information, However, this API is generally called with GetFileVersionInfo and GetFileVersionInfoSize, and its use will be a little cumbersome (mainly in the understanding of the string passed by the second argument), because this is not the use of the API to explain , so it's no longer verbose and interesting to look at MSDN's commentary on this API.

As for this API will occur crash is mainly because some of its internal implementation is not strong enough, in the acquisition of some special sample version information, it is bound to crash, when it comes to special samples, which is why the general use of the situation, basically does not occur, The main problem is that the security software is more likely to encounter a sample scan.

The workaround is similar to the above FindNextFile, which catch the exception to implement a safe function, because the general file version, description and so on is the auxiliary display, not the key logic, so the use of this method is relatively simple and secure.

Inline BOOL apientry verqueryvaluewsafe (const LPVOID pblock, LPTSTR lpsubblock, LPVoid *lplpbuffer, Puint Pulen)

{

BOOL bRet = FALSE;

__try

{

BRet = Verqueryvaluew (pblock, Lpsubblock, Lplpbuffer, Pulen);

}

__except (Exception_execute_handler)

{

BRet = FALSE;

}

return bRet;

}

6, CreateFileMapping related

In fact createfilemapping This API itself has not seen crash, its problems are generally some use of problems and some unavoidable problems resulting in the use of crash in the later.

A common scenario in which a memory-mapped file is used is random reading of the contents of a file, when a file is mapped to memory through CreateFileMapping and mapviewoffile and then randomly read and written. After the mapping is complete, before the read and write, if the file is located on the hard disk volume is unloaded, or mapped is a mobile device (including USB flash drive, mobile hard disk, etc.) file, and the mobile device is unplugged, or a network file, network abnormal disconnection, etc., will immediately trigger a crash, Error ID similar to: 0xc0000006:in page error.

The reason is that the memory map file implementation Mechanism is a bit like virtual memory, he also retained an area of address space, when needed to submit the relevant content to the physical memory, that is not really the beginning of the whole file into memory, but when needed to produce a similar "page break" Response, to the external memory above the relevant content of the file is really mapped to physical memory, if the file is not, or the USB drive is unplugged, then the system can not handle, had to throw an exception.

In fact, this issue has been described in MSDN above: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366801 (v=vs.85). aspx, also gives a solution.

DWORD dwlength;

__try

{

dwlength = * ((lpdword) lpmapaddress);

}

__except (GetExceptionCode () ==exception_in_page_error?

Exception_execute_handler:exception_continue_search)

{

Failed to read from the view.

}

Since the problem cannot be avoided, it may be a good way to end it gracefully. Another way to deal with this problem is to not use memory mapping, and to use APIs like ReadFile to read, you can determine the ReadFile return value to identify this situation.

7, Setdlldirectory

The problem with this API is that there is a bug in the implementation of the setdlldirectory in one version of Microsoft's Kernel32.dll, which calls the thread-synchronous API incorrectly, resulting in a crash of access violations using this API. Later, Microsoft fixed the problem inside the Kernel32.dll. But do not rule out that there are similar problems.

One of the best ways to do this is not to use this API, but to specify the search path for the dynamic link library from the purpose of using this API, so you can use LoadLibraryEx instead, which can be used to specify Load_with_altered_search_ Path temporarily changes the search path. In fact, for security reasons, my advice is to use absolute paths to load DLLs at any time.

http://blog.csdn.net/magictong/article/details/11617135

Some Windows APIs cause crash and Usage issues summary (AV failure of the API, can be processed with try catch capture)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.