I created implementation in MVS without using CRT. I use HeapAlloc() and HeapFree() for allocating memory. My example should work without memory leak.
Here is my code:
LPCSTR byte2ch(BYTE* data, int size) {
char* datas = (char*)HeapAlloc(GetProcessHeap(), NULL, size);
LPCSTR temp = (reinterpret_cast<char const*>(data));
for (int i = 0; i < size; i++) {
datas[i] = temp[i];
}
LPSTR tempo = datas;
HeapFree(GetProcessHeap(), NULL, (LPVOID)&size);
return tempo;
}
int EntryPoint()
{
BYTE* buffer = 0;
HANDLE hFile;
DWORD dwBytesRead, dwBytesWritten, dwPos;
if (hFile = CreateFileW(L"MinerFinder.exe", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL))
{
LARGE_INTEGER size;
GetFileSizeEx(hFile, &size);
buffer = (BYTE*)HeapAlloc(GetProcessHeap(), NULL, size.QuadPart);
ReadFile(hFile, buffer, size.QuadPart, &dwBytesRead, NULL);
MessageBoxA(NULL, byte2ch(buffer, size.QuadPart), NULL, SW_SHOW);
HeapFree(GetProcessHeap(), NULL, (LPVOID)&size.QuadPart);
MessageBoxA(NULL, "", NULL, SW_SHOW); // there I can see, that memory is leaking...
CloseHandle(hFile);
}
ExitProcess(0);
}
Where is my mistake?
EDIT 1:
LPCSTR byte2ch(BYTE* data, int size) {
char* datas = (char*)HeapAlloc(GetProcessHeap(), NULL, size);
LPCSTR temp = (reinterpret_cast<char const*>(data));
for (int i = 0; i < size; i++) {
datas[i] = temp[i];
}
LPSTR tempo = datas;
HeapFree(GetProcessHeap(), NULL, datas);
return tempo;
}
there when I HeapFree() program suddenly crashes. What?
Looking at HeapFree
BOOL HeapFree(
HANDLE hHeap,
DWORD dwFlags,
_Frees_ptr_opt_ LPVOID lpMem
);
lpMem
A pointer to the memory block to be freed. This pointer is returned by the HeapAlloc or HeapReAlloc function. If this pointer is NULL, the behavior is undefined.
In the code
HeapFree(GetProcessHeap(), NULL, (LPVOID)&size);
HeapFree(GetProcessHeap(), NULL, (LPVOID)&size.QuadPart);
You don't give an allocated pointer to HeapFree, but a pointer to the address of some unrelated (non-heap) memory.
The proper call would be
HeapFree(GetProcessHeap(), NULL, datas);
or
HeapFree(GetProcessHeap(), NULL, buffer);
Related
I'm trying to open a file on windows and check that the magic bytes match a windows PE32. If I run the code below and return just before the ReadFile call in the function problemFunction the code works fine and it prints 5a4d at the end of the main function. However if I return after the ReadFile call in problemFunction then I exit in the dos->e_magic != PIMAGE_DOS_HEADER check.
#include <Windows.h>
#include <winternl.h>
void problemFunction(HANDLE *fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(*fh, pByte, fileSize, &dw, NULL);
// could be wrong but i think i need to run SetFilePointer here but not sure on what to do.
return;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(fh == INVALID_HANDLE_VALUE) { CloseHandle(fh); exit(1); }
problemFunction(&fh);
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(fh, pByte, fileSize, &dw, NULL);
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) { CloseHandle(fh); exit(1); }
// dos->e_magic should be 5a4d for MZ, windows PE
}
I assume i need to reset the file pointer after the problemFunction read call with something like
LONG reset = -sizeof(DWORD);
SetFilePointer(*fh, reset, NULL, FILE_END);
But i can't get it to work.
Thanks
There are a number of problems with your code.
problemFunction() is taking a HANDLE* pointer as input, but it is not dereferencing that pointer when passing it to GetFileSize() or CloseHandle(). But it is dereferencing the pointer when passing it to ReadFile().
You must be compiling your code with STRICT Type Checking turned off, otherwise your code would fail to compile. You should always compile with STRICT enabled.
HANDLE is a pointer type, so there is no need to pass it around by pointer, unless you are going to modify its value, which this code is not doing. So you should change problemFunction() to take a HANDLE as-is rather than taking a HANDLE* pointer.
Also, GetFileSize() does not return 0 on failure, like your code assumes. It actually returns INVALID_FILE_SIZE which is -1, ie 0XFFFFFFFF as a DWORD. This is clearly stated in the documentation:
If the function fails and lpFileSizeHigh is NULL, the return value is INVALID_FILE_SIZE. To get extended error information, call GetLastError.
But, most importantly, your 2nd call to ReadFile() inside of main() does not read what you are expecting because the 1st call to ReadFile() inside of problemFunction() has already read the data (and leaked it!), but you are not seeking the HANDLE back to the beginning of the file after that read so the 2nd call to ReadFile() can read it again. You are correct that you need to use SetFilePointer() for that.
With that said, try something more like this:
#include <Windows.h>
#include <winternl.h>
bool test(HANDLE fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
return false;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL)) {
delete[] pByte;
return false;
}
// use pByte as needed...
delete[] pByte;
if (SetFilePointer(fh, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
return false;
}
return true;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
return 1;
}
if (!test(fh)) {
CloseHandle(fh);
return 1;
}
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
CloseHandle(fh);
return 1;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL) || dw < sizeof(IMAGE_DOS_HEADER)) {
CloseHandle(fh);
return 1;
}
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
delete[] pByte;
CloseHandle(fh);
return 1;
}
...
delete[] pByte;
CloseHandle(fh);
return 0;
}
I have question: when I'm trying to generate AES key 128 lenght with CryptGenKey I have data leak?
Code below:
void GeKey(HCRYPTKEY hKey, HCRYPTPROV hProvs)
{
DWORD len_iv = 0;
if (!CryptGenKey(hProvs, CALG_AES_128, CRYPT_EXPORTABLE, &hKey))
{
ExitProcess(0);
}
if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, NULL, &len_iv))
{
ExitProcess(0);
}
unsigned char* aes_key_dec = new unsigned char[len_iv];
if (!CryptExportKey(hKey, NULL, PLAINTEXTKEYBLOB, NULL, aes_key_dec, &len_iv))
{
ExitProcess(0);
}
for (int i = 0; i < len_iv; i++)
{
printf("%c", aes_key_dec[i]);
}
printf("\n\n");
delete[] aes_key_dec;
}
delete[] aes_key_dec; can't help me with this issue. What's wrong :/
I try to write dll injector with nativeApi. For this reason, i wrote this code. NtReadFile function reads something but i cant see anything except for the first value of FileReadBuffer. Also, i dont know anything about how does dll look into buffer.
(1)How can i compare buffer and dll file?
(2)How can i be sure the code runs correct.
(3)And please tell me my mistake in the code.
bool Injector::initiationDll(const std::string& dllPath)
{
if (!isDllExist(dllPath))
{
printf("Dll not found!\n");
return false;
}
else
{
printf("LibraryPath: %s\n", dllPath);
NTSTATUS status; HANDLE lFile;
OBJECT_ATTRIBUTES objAttribs = { 0 }; UNICODE_STRING unicodeString;
std::string dllPathWithprefix = "\\??\\" + dllPath;
std::wstring wString = std::wstring(dllPathWithprefix.begin(), dllPathWithprefix.end()); PCWSTR toPcwstr = wString.c_str();
RtlInitUnicodeString(&unicodeString, toPcwstr);
InitializeObjectAttributes(&objAttribs, &unicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
objAttribs.Attributes = 0;
const int allocSize = 2048;
LARGE_INTEGER largeInteger;
largeInteger.QuadPart = allocSize;
IO_STATUS_BLOCK ioStatusBlock;
status = NtCreateFile(
&lFile,
GENERIC_READ | FILE_READ_DATA | SYNCHRONIZE,
&objAttribs,
&ioStatusBlock,
&largeInteger,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(status)) {
printf("CreateFile failed..\n");
return false;
}
else {
printf("Library Handle : %p\n", lFile);
DWORD fileSize = getDllSize(dllPath);
if (fileSize == 0)
{
printf("File size is zero.\n");
return false;
}
else
{
printf("File size : %d byte.\n", fileSize);
PVOID FileReadBuffer = VirtualAlloc(NULL, fileSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!FileReadBuffer)
{
printf("\nError: Unable to allocate memory(%d)\n", GetLastError());
status = NtClose(lFile);
return false;
}
else {
printf("Allocate %d byte for buffer.\n", fileSize);
status = NtReadFile(
lFile,
NULL,
NULL,
NULL,
&ioStatusBlock,
FileReadBuffer,
sizeof(FileReadBuffer),
0, // ByteOffset
NULL);
if (!NT_SUCCESS(status))
{
printf("Unable to read the dll... : %d\n", GetLastError());
return false;
}
else {
status = NtClose(lFile);
for (int i = 0; i < sizeof(fileSize); i++)
{
//wprintf(L"%p : %s\n", FileReadBuffer, FileReadBuffer);
}
}
}
}
}
}
}
status = NtReadFile(
lFile,
NULL,
NULL,
NULL,
&ioStatusBlock,
FileReadBuffer,
sizeof(FileReadBuffer), // !!!!!
0, // ByteOffset
NULL);
so you read sizeof(FileReadBuffer) - 4 or 8 bytes only. i view you use my advice from here
Here is my attempt:
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <string>
// Forward declarations:
void append(LPCTSTR, LPCVOID, DWORD);
void readTail(LPCTSTR, LPVOID, DWORD);
int main()
{
LPCTSTR fn = L"C:/kaiyin/kybig.out";
LPCVOID buf = "eeeee";
append(fn, buf, 5);
LPVOID buf1 = "";
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
printf("hello world\n");
std::string s = "";
std::getline(std::cin, s);
return 0;
}
void append(LPCTSTR filename, LPCVOID buf, DWORD writeSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
WriteFile(fh, buf, writeSize, NULL, NULL);
CloseHandle(fh);
}
void readTail(LPCTSTR filename, LPVOID buf, DWORD readSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
size.QuadPart -= readSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
ReadFile(fh, buf, readSize, NULL, NULL);
CloseHandle(fh);
}
The append function seems to increase the file size by the correct number (5 bytes), but printing the last 5 byte to in the console doesn't show anything.
What went wrong?
You have not allocated buffer for your result:
LPVOID buf1 = "";
readTail(fn, buf1, 5);
buf1 is only a pointer to empty string, what you want is some buffer where to put your results:
BYTE buf1[10] = { 0 };
readTail(fn, buf1, 5);
Also, you are appending initialy to existing file (due to OPEN_EXISTING),so makesure you have an empty C:/kaiyin/kybig.out file.
Just for the record, here is the modified code according to suggestions from #marcinj :
// ConsoleApplication1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <iostream>
#include <string>
// Forward declarations:
void append(LPCTSTR, LPCVOID, DWORD);
void readTail(LPCTSTR, LPVOID, DWORD);
void truncateTail(LPCTSTR, long);
int main()
{
LPCTSTR fn = L"C:/kaiyin/kybig.out";
char buf[] = "helloWorld";
append(fn, buf, 10);
BYTE buf1[10] = {0};
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
truncateTail(fn, 5);
for (int i = 0; i < 10; i++) {
buf1[i] = 0;
}
readTail(fn, buf1, 5);
std::cout << (char*) buf1 << std::endl;
printf("End of program\n");
std::string s = "";
std::getline(std::cin, s);
return 0;
}
void append(LPCTSTR filename, LPCVOID buf, DWORD writeSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
WriteFile(fh, buf, writeSize, NULL, NULL);
CloseHandle(fh);
}
void readTail(LPCTSTR filename, LPVOID buf, DWORD readSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
GetFileSizeEx(fh, &size);
size.QuadPart -= readSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
ReadFile(fh, buf, readSize, NULL, NULL);
CloseHandle(fh);
}
void truncateTail(LPCTSTR filename, long truncateSize) {
LARGE_INTEGER size;
size.QuadPart = 0;
HANDLE fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
std::cerr << GetLastError();
return;
}
GetFileSizeEx(fh, &size);
size.QuadPart -= truncateSize;
SetFilePointerEx(fh, size, NULL, FILE_BEGIN);
if (SetEndOfFile(fh) == 0) {
std::cerr << GetLastError();
return;
}
CloseHandle(fh);
}
I am trying to print info about registry. My problem is in the first for loop.
I can't get it to print dataType and data correctly.
Also, adding them in the same print will crash the program or not print correctly.
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
void EnumerateValues(HKEY hKey, DWORD numValues)
{
DWORD dwIndex = 0;
LPSTR valueName = new CHAR[64];
DWORD valNameLen;
DWORD dataType;
DWORD data;
DWORD dataSize;
for (int i = 0; i < numValues; i++)
{
RegEnumValue(hKey,
dwIndex,
valueName,
&valNameLen,
NULL,
&dataType,
(BYTE*)&data,
&dataSize);
dwIndex++;
_tprintf(TEXT("(%d) %s %d\n"), i+1, valueName, dataType);
// printf("Code: 0x%08X\n", data);
}
}
void EnumerateSubKeys(HKEY RootKey, char* subKey, unsigned int tabs = 0)
{
HKEY hKey;
DWORD cSubKeys; //Used to store the number of Subkeys
DWORD maxSubkeyLen; //Longest Subkey name length
DWORD cValues; //Used to store the number of Subkeys
DWORD maxValueLen; //Longest Subkey name length
DWORD retCode; //Return values of calls
RegOpenKeyEx(RootKey, subKey, 0, KEY_ALL_ACCESS, &hKey);
RegQueryInfoKey(hKey, // key handle
NULL, // buffer for class name
NULL, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&maxSubkeyLen, // longest subkey length
NULL, // longest class string
&cValues, // number of values for this key
&maxValueLen, // longest value name
NULL, // longest value data
NULL, // security descriptor
NULL); // last write time
if(cSubKeys>0)
{
char currentSubkey[MAX_PATH];
for(int i=0;i < cSubKeys;i++){
DWORD currentSubLen=MAX_PATH;
retCode=RegEnumKeyEx(hKey, // Handle to an open/predefined key
i, // Index of the subkey to retrieve.
currentSubkey, // buffer to receives the name of the subkey
¤tSubLen, // size of that buffer
NULL, // Reserved
NULL, // buffer for class string
NULL, // size of that buffer
NULL); // last write time
if(retCode==ERROR_SUCCESS)
{
for (int i = 0; i < tabs; i++)
printf("\t");
printf("(%d) %s\n", i+1, currentSubkey);
char* subKeyPath = new char[currentSubLen + strlen(subKey)];
sprintf(subKeyPath, "%s\\%s", subKey, currentSubkey);
EnumerateSubKeys(RootKey, subKeyPath, (tabs + 1));
}
}
}
else
{
EnumerateValues(hKey, cValues);
}
RegCloseKey(hKey);
}
int main()
{
EnumerateSubKeys(HKEY_CURRENT_USER,"SOFTWARE\\Dropbox");
getchar();
return 0;
}
Your call to RegEnumValue is incorrect. It has the following problems:
You are expected to initialise valNameLen before calling the function.
You are expected to initialise dataSize before calling the function.
You fail to check the return value of RegEnumValue and thus assume that the function succeeds. And in fact it fails because you of the aforementioned errors.
Let's ignore the value for now, since that's much more complex. Let's just try and enumerate the names of the values. That code would look like this:
void EnumerateValues(HKEY hKey, DWORD numValues)
{
for (DWORD dwIndex = 0; dwIndex < numValues; dwIndex++)
{
char valueName[64];
DWORD valNameLen = sizeof(valueName);
DWORD dataType;
DWORD dataSize = 0;
DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
NULL, &dataType, NULL, &dataSize);
if (retval == ERROR_SUCCESS)
{
printf("(%d) %s %d\n", dwIndex+1, valueName, dataType);
}
else
{
// handle error
}
}
}
Note also that I stopped using a dynamically allocated character array as your code did. Your code leaked that array. Obviously if you need to cope with arbitrarily large value names, then you would need to use dynamically allocated arrays.
As for extracting the data, that's a bigger task that I don't believe is in the scope of
this question. You need special code for each individual data type.
For instance, to read a REG_SZ you would use code like this:
char *data = new char [dataSize+1];
data[dataSize] = '\0';
valNameLen = sizeof(valueName);
DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
NULL, NULL, (LPBYTE)data, &dataSize);
if (retval == ERROR_SUCCESS)
{
printf("(%d) %s %d %s\n", dwIndex+1, valueName, dataType, data);
}
else
{
// handle error
}
delete[] data;