2016-01-15 3 views
1

Первое, что первый:Зашифрованные API вызовов неудачу

Мои тест-системы: Windows 7 32 бит Professional для Windows 7 64 бит Professional

Компилятор: GCC версии 5.2.0 (i686-win32-карлик-rev0 , Построенный по проекту MinGW-W64) вариантов

Строительства: г ++ foo.cpp -o foo.exe

Мое приложение получает адреса функций из kernel32.dll динамически. Это работает по назначению. Однако, когда я шифрую эти вызовы API и передаю расшифрованную строку функции GetProcAdress, она не работает в зависимости от порядка char pVAE_D [strlen (pVAE_E)]; и char pGTC_D [strlen (pGTC_E)], а также порядок зашифрованных строк; Если установить символ pGTC_D [STRLEN (pGTC_E)], прежде чем символ pVAE_D [STRLEN (pVAE_E)] (то же самое для зашифрованных строк)

`#include <windows.h> 
#include <stdio.h> 

typedef BOOL(WINAPI* _GetThreadContext) 
(HANDLE hThread, 
LPCONTEXT lpContext 
); 

typedef LPVOID(WINAPI* _VirtualAllocEx) 
(HANDLE handle_Process, 
LPVOID longpointer_Address, 
SIZE_T dwSize, 
DWORD flAllocationType, 
DWORD flProtect 
); 

void encrStr(char *pStr, int len, char *pOut, char cryptochar); 

int main(void) 
{ 
char pVAE_E[] = {0x32, 0x0d, 0x16, 0x10, 0x11, 0x05, 0x08, 0x25, 0x08, 0x08, 

0x0b, 0x07, 0x21, 0x1c, 0x00}; // VirtualAllocEx encrypted with d 

char pGTC_E[] = { 
0x3d, 0x1f, 0x0e, 0x2e, 0x12, 0x08, 0x1f, 0x1b, 0x1e, 0x39, 0x15, 0x14, 
0x0e, 0x1f, 0x02, 0x0e, 0x00}; // GetThreadContext encrypted with z 

char pVAE_D[strlen(pVAE_E)]; 
char pGTC_D[strlen(pGTC_E)]; 


encrStr(pVAE_E, strlen(pVAE_E), pVAE_D, 'd'); 
encrStr(pGTC_E, strlen(pGTC_E), pGTC_D, 'z'); 
HMODULE hKernel32 = LoadLibraryA("kernel32.dll"); 

FARPROC fpGetThreadContext = GetProcAddress(hKernel32, pGTC_D); 
if (fpGetThreadContext == NULL) 
{ 
    printf("gtc failed.\n"); 
} 

_GetThreadContext kernel32GetThreadContext =  

(_GetThreadContext)fpGetThreadContext; 

FARPROC fpVirtualAllocEx = GetProcAddress(hKernel32, pVAE_D); 
if (fpVirtualAllocEx == NULL) 
{ 
    printf("vae failed.\n"); 
} 
_VirtualAllocEx kernel32VirtualAllocEx = (_VirtualAllocEx)fpVirtualAllocEx; 


} 

void encrStr(char *pStr, int len, char *pOut, char cryptochar) 
{ 
// zero char must remain, therefore i < len 
for (int i = 0; i < len; i++) 
{ 
    pOut[i] = pStr[i]^cryptochar; 
    printf("%c\n", pOut[i]); 
} 
pOut[len] = 0x00; 
printf("%s\n", pOut); 
}` 

Если я увеличить размер памяти буфера дешифрования на 1 он работает независимо от порядок присвоения. Почему это происходит иначе?

+0

Пожалуйста раздеться неродственной информацией и кодом из вашего вопроса, и сосредоточиться на проблеме, которую вы имеете. Предоставьте [MCVE] (http://stackoverflow.com/help/mcve) (акцент на * минимальный *). Вызовы «LoadLibraryA», «GetProcAddress» и связанные с ними вызовы указателей функций не связаны с проблемой вообще. – IInspectable

+1

обычно 'pOut [len]' недействительный индекс. Последним элементом, вероятно, должно быть 'pOut [len-1]' –

ответ

1

Это две проблемы с вашим кодом. Во-первых, вы используете strlen для определения размера буферов для дешифрованных строк . Эта функция не учитывает символ нуль-терминатора '\ 0' (который равен 0x00 в вашем случае ). Это означает, что буферы pVAE_D и pGTC_D будут иметь один элемент меньше, чем их соответствующие буферы , содержащие зашифрованные строки. Вторая проблема - ваша функция encrStr. В нем вы пишете за пределами границы массива с оператором pOut[len] = 0x00;. Индексы для доступа к массиву находятся в диапазоне [0, len - 1]. Это как ваша функция (при условии, что вы передаете выходной буфер с достаточно элементов для строки и ее нуль-терминатором) должны быть реализованы:

void encrStr(char *pStr, int len, char *pOut, char cryptochar) 
{ 
    // zero char must remain, therefore i < len 
    for (int i = 0; i < len - 1; i++) 
    { 
     pOut[i] = pStr[i]^cryptochar; 
     printf("%c\n", pOut[i]); 
    } 
    pOut[len - 1] = 0x00; 
    printf("%s\n", pOut); 
} 

Когда вы пишете за пределы массива, развращают стек вокруг вашего массива, и вы сталкиваетесь с UB (неопределенное поведение). Вот почему этот образец иногда работает, а иногда он этого не делает. Некоторые компиляторы будут предупреждают вас об этом, но другие не будут. Это тонкие ошибки на C++, которые могут вызвать у вас большую головную боль. Checkout эти ссылки для получения дополнительной информации о неопределенном поведении:

What are all the common undefined behaviours that a C++ programmer should know about?

https://en.wikipedia.org/wiki/Undefined_behavior

+0

Спасибо, что в значительной степени решила проблему, я понимаю, почему она потерпела неудачу. Я перекомпилировал его с вашим улучшенным образцом кода, он работает правильно. – lambda

Смежные вопросы