依旧是用远程注入线程的方式注入代码执行。
代码与数据得分两部分写入目标程序,然后再执行。
贴出实例
//CODETYPE.H
#include "windows.h"
typedef struct _THREAD_PARAM
{
FARPROC pFunc[2]; // LoadLibraryA(), GetProcAddress()
char szBuf[4][128]; // "user32.dll", "MessageBoxA", "www.reversecore.com", "ReverseCore"
} THREAD_PARAM, *PTHREAD_PARAM;
typedef HMODULE(WINAPI *PFLOADLIBRARYA)
(
LPCSTR lpLibFileName
);
typedef FARPROC(WINAPI *PFGETPROCADDRESS)
(
HMODULE hModule,
LPCSTR lpProcName
);
typedef int (WINAPI *PFMESSAGEBOXA)
(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
typedef DWORD(WINAPI *THREADPROC)
(
LPVOID lParam
);
//injectcode.h
#pragma once
#include "codetype.h"
class InjectCode
{
public:
InjectCode();
~InjectCode();
BOOL Inject(DWORD dwPID,int codesize,THREADPROC ThreadProc,THREAD_PARAM ¶m)
{
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
LPVOID pRemoteBuf[2] = { 0, };
DWORD dwSize = 0;
// Open Process
if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, // dwDesiredAccess
FALSE, // bInheritHandle
dwPID))) // dwProcessId
{
printf("OpenProcess() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// Allocation for THREAD_PARAM
dwSize = sizeof(THREAD_PARAM);
if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess, // hProcess
NULL, // lpAddress
dwSize, // dwSize
MEM_COMMIT, // flAllocationType
PAGE_READWRITE))) // flProtect
{
printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
return FALSE;
}
if (!WriteProcessMemory(hProcess, // hProcess
pRemoteBuf[0], // lpBaseAddress
(LPVOID)¶m, // lpBuffer
dwSize, // nSize
NULL)) // [out] lpNumberOfBytesWritten
{
printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
return FALSE;
}
// Allocation for ThreadProc()
dwSize = codesize;
if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess, // hProcess
NULL, // lpAddress
dwSize, // dwSize
MEM_COMMIT, // flAllocationType
PAGE_EXECUTE_READWRITE))) // flProtect
{
printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
return FALSE;
}
if (!WriteProcessMemory(hProcess, // hProcess
pRemoteBuf[1], // lpBaseAddress
(LPVOID)ThreadProc, // lpBuffer
dwSize, // nSize
NULL)) // [out] lpNumberOfBytesWritten
{
printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
return FALSE;
}
if (!(hThread = CreateRemoteThread(hProcess, // hProcess
NULL, // lpThreadAttributes
0, // dwStackSize
(LPTHREAD_START_ROUTINE)pRemoteBuf[1], // dwStackSize
pRemoteBuf[0], // lpParameter
0, // dwCreationFlags
NULL))) // lpThreadId
{
printf("CreateRemoteThread() fail : err_code = %d\n", GetLastError());
return FALSE;
}
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
};
//调用
#include "stdafx.h"
#include "InjectCode.h"
DWORD WINAPI ThreadProc(LPVOID lParam)
{
PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;
HMODULE hMod = NULL;
FARPROC pFunc = NULL;
// LoadLibrary()
hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]); // "user32.dll"
if (!hMod)
return 1;
// GetProcAddress()
pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]); // "MessageBoxA"
if (!pFunc)
return 1;
// MessageBoxA()
((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
return 0;
}
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
{
printf("OpenProcessToken error: %u\n", GetLastError());
return FALSE;
}
if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError());
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError());
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hMod = NULL;
THREAD_PARAM param = { 0, };
DWORD dwPID = 0;
if (argc != 2)
{
printf("\n USAGE : %s <pid>\n", argv[0]);
return 1;
}
hMod = GetModuleHandleA("kernel32.dll");
// set THREAD_PARAM
param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
strcpy_s(param.szBuf[0], "user32.dll");
strcpy_s(param.szBuf[1], "MessageBoxA");
strcpy_s(param.szBuf[2], "www.reversecore.com");
strcpy_s(param.szBuf[3], "ReverseCore");
// change privilege
if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
return 1;
// code injection
dwPID = (DWORD)_wtol(argv[1]);
InjectCode ic;
ic.Inject(dwPID, (DWORD)SetPrivilege - (DWORD)ThreadProc, ThreadProc, param);
return 0;
}
//这些都是基础的注入方法,若干年前的WINDOWS核心编程里就有详细的分析与实例,今天看这本韩国逆向高手写的逆向工程核心原理之书,依旧用的是旧技术,新的DLL代码注入没有提及(不是DLL注入,是DLL代码注入),有些小失望,看章节,后面还有机器码注入,这也是老技术了,新的APC之类的一概没有提及。。。
//附一点,此书中关于OD的断点方法倒是以前没有用过,挺好用,比如断DLL加载,断线程加载,选项-》调试设置-》事件-》中断于新线程,中断于新模块。。。很让人有些启发。。。惭愧,OD的好多功能居然还不知道。。。