2016-09-14 5 views
0

Я хочу подключить функцию WriteFile. Целевой процесс notepad.exe. Но это не сработает. Код.Я хочу подключить win32API, но он не работает

#include<stdio.h> 
#include<stdlib.h> 
#include<Windows.h> 
#include<TlHelp32.h> 


DEBUG_EVENT de; 
FARPROC g_pfTargetAPIAddress; //save the address of WriteFile function 
BYTE g_ReadAPIBuffer;   //save the original content of the first byte of WriteFile function 
BYTE g_WriteAPIBuffer=0xCC; //change the first byte of WriteFile function to 0xCC , so that it can throw a breakpoint exception 
HANDLE g_hTargetProcessHandle; //the handle of the target process (notepad.exe) 
HANDLE g_hTargetThreadHandle; //the main thread of the target process 
DWORD g_dwTargetProcessId;  
DWORD g_dwTargetThreadId; 


DWORD GetTargetProcess() //get the id of the target process (notepad.exe) 
{ 

PROCESSENTRY32 pe32; 
pe32.dwSize=sizeof(pe32); 


HANDLE handle=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); 
if(handle==INVALID_HANDLE_VALUE) 
{ 
    printf("get tool help handle error,the error code is:%u\n",GetLastError()); 
    system("PAUSE"); 
    return NULL; 
} 

BOOL bMore=::Process32First(handle,&pe32); 
while(bMore) 
{ 
    printf("the process name is:%ws\n",pe32.szExeFile); 
    printf("the process id is %d\n",pe32.th32ProcessID); 

    if(wcscmp(pe32.szExeFile,L"notepad.exe")==0) 
    { 
     return pe32.th32ParentProcessID; 
    } 

    bMore=::Process32Next(handle,&pe32); 
} 

return NULL; 

} 


BOOL OnProcessCreateDebug(LPDEBUG_EVENT de) 
{ 

printf("now begin OnProcessCreateDebug\n"); 
g_hTargetProcessHandle=de->u.CreateProcessInfo.hProcess; 
g_hTargetThreadHandle=de->u.CreateProcessInfo.hThread; 
g_dwTargetThreadId=de->dwThreadId; 

HMODULE hModule=::LoadLibrary(L"kernel32.dll"); 
if(hModule==INVALID_HANDLE_VALUE) 
{ 
    printf("get the api handle error ,the error code is :%u\n",GetLastError()); 
    system("PAUSE"); 
    return FALSE; 
} 

char cTargetAPIName[]="WriteFile"; 
g_pfTargetAPIAddress=::GetProcAddress(hModule,(LPCSTR)cTargetAPIName); 
if(g_pfTargetAPIAddress==NULL) 
{ 
    printf("the getprocaddress in onprocesscreatedebug failes,the error code is:%u",GetLastError()); 
    system("PAUSE"); 
    return FALSE; 
} 


BOOL bReadResult=::ReadProcessMemory(de->u.CreateProcessInfo.hProcess,g_pfTargetAPIAddress,&g_ReadAPIBuffer,sizeof(BYTE),NULL); 
if(!bReadResult) 
{ 
    printf("read the first byte of target api fails,the error code is :%u\n",GetLastError()); 
    system("PAUSE"); 
    return FALSE; 
} 



BOOL bWriteResult=::WriteProcessMemory(de->u.CreateProcessInfo.hProcess,g_pfTargetAPIAddress,&g_WriteAPIBuffer,sizeof(BYTE),NULL); 
if(!bWriteResult) 
{ 
    printf("write the first byte of target api fails,the error code is :%u\n",GetLastError()); 
    system("PAUSE"); 
    return FALSE; 

} 

printf("now finish OnProcessCreateDebugEvent\n"); 

return TRUE; 

} 


BOOL OnExceptionDebugEvent(LPDEBUG_EVENT de) 
{ 

printf("now go into the OnExceptionDebugEvent just now\n"); 
PEXCEPTION_RECORD per=&de->u.Exception.ExceptionRecord; 

if(per->ExceptionCode==EXCEPTION_BREAKPOINT) 
{ 

    printf("now it is in the first if\n"); 

    if(per->ExceptionAddress==g_pfTargetAPIAddress) 
    { 

     printf("now has entered the OnExceptionDebugEvent\n"); 


     if(!WriteProcessMemory(g_hTargetProcessHandle,g_pfTargetAPIAddress,&g_WriteAPIBuffer,sizeof(BYTE),NULL)) 
     { 
      printf("onexecption write the first byte of target api fails,the error code is :%u\n",GetLastError()); 
      system("PAUSE"); 
      return FALSE; 
     } 


     CONTEXT con; 
     con.ContextFlags=CONTEXT_CONTROL; 
     ::GetThreadContext(g_hTargetThreadHandle,&con); 

     DWORD dwWriteFileBufferAddress; 
     if(!::ReadProcessMemory(g_hTargetProcessHandle,(LPCVOID)(con.Esp+0x8),&dwWriteFileBufferAddress,sizeof(DWORD),NULL)) 
     { 
      printf("read the the lpBaseAddress of target api fails,the error code is :%u\n",GetLastError()); 
      system("PAUSE"); 
      return FALSE; 
     } 


     printf("now after esp+8\n"); 

     DWORD dwSizeOfBuffer; 
     if(!::ReadProcessMemory(g_hTargetProcessHandle,(LPCVOID)(con.Esp+0x10),&dwSizeOfBuffer,sizeof(DWORD),NULL)) 
     { 
      printf("read the lpBuffer of target api fails,the error code is :%u\n",GetLastError()); 
      system("PAUSE"); 
      return FALSE; 
     } 


     LPBYTE lpBuffer=(LPBYTE)malloc(dwSizeOfBuffer+1); 
     LPBYTE lppointer=lpBuffer; 
     for(int i=0;i<=dwSizeOfBuffer;i++) 
     { 
      *lppointer=0x1; 
      lppointer++; 
     } 
     *lppointer=0x0; 

     if(!::WriteProcessMemory(g_hTargetProcessHandle,(LPVOID)dwWriteFileBufferAddress,lpBuffer,dwSizeOfBuffer+1,NULL)) 
     { 
      printf("overridewrite the buffer of target api fails,the error code is :%u\n",GetLastError()); 
      system("PAUSE"); 
      return FALSE; 
     } 

     free(lpBuffer); 


     con.Eip=(DWORD)g_pfTargetAPIAddress; 
     SetThreadContext(g_hTargetThreadHandle,&con); 

     ContinueDebugEvent(g_dwTargetProcessId,g_dwTargetThreadId,DBG_CONTINUE); 


     printf("now after the ContinueDebugEvent\n"); 

     Sleep(0); 

     BYTE byte=0xcc; 
     if(!::WriteProcessMemory(g_hTargetProcessHandle,g_pfTargetAPIAddress,&byte,sizeof(BYTE),NULL)) 
     { 
      printf("rewrite the first byte of target api fails,the error code is :%u\n",GetLastError()); 
      system("PAUSE"); 
      return FALSE; 
     } 

    } 

    else 
     { 
      printf("not enter the second if\n"); 
     } 
} 


else printf("not enter the first if\n"); 

return TRUE; 
} 


BOOL HookAPI() 
{ 
while(WaitForDebugEvent(&de,INFINITE)) 
{ 
    if(de.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT) 
    { 
     if(!OnProcessCreateDebug(&de)) return FALSE; 

    } 


    else if(de.dwDebugEventCode==EXCEPTION_DEBUG_EVENT) 
    { 
     printf("now it is going to call the OnExceptionDebugEvent\n"); 
     if(!OnExceptionDebugEvent(&de)) return FALSE; 
    } 
    else if(de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT) 
    { 
     break; 
    } 


    ::ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE); 

} 
return TRUE; 
} 


int main() 
{ 
g_dwTargetProcessId=GetTargetProcess(); 
if(g_dwTargetProcessId==NULL) 
{ 
    printf("the value of dProcessId is null\n"); 
    system("PAUSE"); 
    return -1; 
} 


BOOL b=DebugActiveProcess(g_dwTargetProcessId); 
if(!b) 
{ 
    printf("DebugActiveProcess fails,the last error is : %u\n",GetLastError()); 
    system("PAUSE"); 
    return -1; 
} 

HookAPI(); 

return 0; 
} 

Я хочу, чтобы подключить функцию WriteFile, и она меняет первые байты WriteFile функции в 0xCC, но она не работает. Я могу сохранить файл как обычно, используя notepad.exe. Я думаю, что 0xCC не может выбрасывать исключение точки останова. Кто-нибудь скажет мне, где проблема?

+1

Похоже, вы уверены, что 'notepad.exe' является 32-битным, но в наши дни это редко бывает так. Взаимодействие API в 64-битных программах несколько отличается. – Havenard

+0

AFAIK 'notepad.exe' отображает файл, который вы редактируете, в память, поэтому он, вероятно, часто не использует' WriteFile'. –

+0

@Havenard Я просто изучаю и эту программу я запускаю только на 32-битной Windows Xp sp3 – freedomwings

ответ

1

Этот код может быть скомпилирован только в среде x86, поскольку структура CONTEXT будет иметь совершенно другой набор полей для x64 процессоров. Поскольку сейчас действуют x64, то notepad.exe, скорее всего, является x64, поэтому ваше приложение x86 не сможет подключиться к нему. DebugActiveProcess вернет FALSE, с GetLastError == ERROR_NOT_SUPPORTED. Если мы на мгновение проигнорируем эту вещь для биты (или предположим, что блокнот - это приложение x86), в вашем коде есть кое-что, что нужно улучшить.

Первый. Этот код проверки ошибок недопустим:

HMODULE hModule = ::LoadLibrary(L"kernel32.dll"); 
if (hModule == INVALID_HANDLE_VALUE) 
{ 
    printf("get the api handle error ,the error code is :%u\n", GetLastError()); 
    system("PAUSE"); 
    return FALSE; 
} 

LoadLibrary возвращает NULL на ошибку, INVALID_HANDLE_VALUE -1, так что ваш обработчик ошибок никогда не будет вызван. В то время как kernel32.dll отсутствие совершенно невозможно, это следует учитывать и для других DLL.

Второй. Вы не можете отлаживать другой процесс, если не можете открыть его дескриптор с помощью маски доступа PROCESS_ALL_ACCESS. Настройка SE_DEBUG_NAME привилегия также может помочь. Чтобы включить эту привилегию, ваша учетная запись должна иметь права администратора (или эта привилегия должна быть включена в групповой политике). Даже если учетная запись имеет SE_DEBUG_NAME, она должна быть явно запрошена приложением. См. this Пример MSDN для деталей.

В-третьих. Страницы кода Dll защищены от записи. Поэтому вы должны использовать VirtualProtectEx для изменения защиты памяти на PAGE_EXECUTE_READWRITE

Четвертый. Вы не можете предположить, что одна и та же DLL будет иметь одинаковый адрес загрузки в разных процессах. Dll может быть переустановлена ​​на нагрузке, если есть конфликт с каким-либо другим адресом загрузки базы данных dll. Кроме того, во всех современных ОС Windows с Windows Vista есть функция безопасности, называемая рандомизацией макета пространства адресов (ASLR). Таким образом, вам нужно перечислить DLL в целевом процессе с помощью API ToolHelp, а просто вызвать GetProcAddress.

+1

'WriteProcessMemory' actualy действительно меняет защиту страницы (временно). –

+0

Я запускаю эту программу на Windows XP sp3, и у нее нет ASLR. И я думаю, что ASLR перезагружает базовый адрес DLL и другой процесс при перезагрузке компьютера. Но все базовые адреса dll в системе одинаковы. – freedomwings