逆向 | shellcode注入模板
逆向 | shellcode注入模板
继续写书里的示例代码。顺便补一张原理图,画了我半天:
#include <stdio.h>
#include <windows.h>
typedef int (WINAPI* PMESSAGEBOXA)(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption, UINT uType);
typedef FARPROC (WINAPI* PGETPROCADDRESS)(HMODULE hModule,LPCSTR lpProcName);
typedef HMODULE (WINAPI* PLOADLIBRARY)(LPCTSTR lpFileName);
/*
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;
*/
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks; // 3个双向链表
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
UINT SizeOfImage; // 这里32位的就是UINT 64位是UINT64
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName; // 查找这个
//...
}LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
void shellcode(){
// 准备字符串备用
// wchar_t wsKernel32Dll[] = L"kernel32.dll";
char wsKernel32Dll[] = {'K', 0, 'E', 0, 'R', 0, 'N', 0, 'E', 0, 'L', 0, '3', 0, '2', 0, '.', 0, 'D', 0, 'L', 0, 'L', 0, 0, 0};
char sUser32Dll[] = {'U', 'S', 'E', 'R', '3', '2', '.', 'd', 'l', 'l', 0};
char sGetProcAddr[] = {'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0};
char sLoadLibraryA[] = {'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', 0};
char sMessageBoxA[] = {'M', 'e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'A', 0};
// 通过fs:[0x30]查找PEB 找到3个链表 找到K32.dll
/*
_PEB_LDR_DATA
[0] Length
[4] Initialized
[8] SsHandle
[c] InLoadOrderModuleList : _LIST_ENTRY
[14] InMemoryOrderModuleList : _LIST_ENTRY
[1c] InInitializationOrderModuleList : _LIST_ENTRY
...
*/
DWORD pBeg = 0;
DWORD pPLD = 0;
PLIST_ENTRY pInLoadOrderModuleList = 0;
__asm{
pushad
mov eax, fs:[0x30] ; PEB
mov eax, [eax+0x0c] ; PEB->Ldr
add eax, 0x0c ; _PEB_LDR_DATA->InLoadOrderModuleList
lea ebx, dword ptr [pInLoadOrderModuleList] ; 获取InLoadOrderModuleList的地址保存在变量中
mov [ebx], eax;
popad
}
//printf("InLoadOrderModuleList: %p %p \n",pInLoadOrderModuleList->Flink, pInLoadOrderModuleList->Blink);
// 拿到第一个LDR_DATA_TABLE_ENTRY节点的地址
PLDR_DATA_TABLE_ENTRY pFirstLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pInLoadOrderModuleList->Flink;
// 循环遍历所有的模块 查找kernel32.dll
DWORD dwKernel32Base = 0;
PLDR_DATA_TABLE_ENTRY pLdrDataEntry = pFirstLdrDataEntry;
while(1){
//printf("[%p] %p %p \n", pLdrDataEntry, pLdrDataEntry->InLoadOrderLinks.Flink, pLdrDataEntry->InLoadOrderLinks.Blink);
//printf(" [%S(%p)] %S \n", pLdrDataEntry->BaseDllName.Buffer, pLdrDataEntry->DllBase, pLdrDataEntry->FullDllName.Buffer);
if (pLdrDataEntry->InLoadOrderLinks.Flink == (PLIST_ENTRY)pFirstLdrDataEntry){
break;
}
// 判断是不是kernel32.dll
/*
if(wcsicmp(pLdrDataEntry->BaseDllName.Buffer, (wchar_t*)wsKernel32Dll) == 0){
//printf("~~~~~~ find it! ~~~~~~~\n");
dwKernel32Base = (DWORD)pLdrDataEntry->DllBase;
}
*/
// 手动编写wcscmp
wchar_t* wtmp = (wchar_t*)(pLdrDataEntry->BaseDllName.Buffer);
int index = 0;
int length = 0;
while(((wchar_t*)wsKernel32Dll)[index] != 0){ // 计算长度
index ++;
}
length = index;
for (index = 0; index < length; index ++){ // 对比
if (((wchar_t*)wsKernel32Dll)[index] != wtmp[index]){
break;
}
}
if (index == length){ // 找到了
//puts("found"); // 找到kernel32.dll
dwKernel32Base = (DWORD)pLdrDataEntry->DllBase;
}
pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)pLdrDataEntry->InLoadOrderLinks.Flink;
}
//printf("kernel32.dll base: %p \n", dwKernel32Base); // 拿到kernel32.dll基址
// 通过导出表查找LoadLibrary
PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)dwKernel32Base;
PIMAGE_NT_HEADERS pINHS = (PIMAGE_NT_HEADERS)(dwKernel32Base+pIDH->e_lfanew);
PIMAGE_EXPORT_DIRECTORY pIED = (PIMAGE_EXPORT_DIRECTORY)(dwKernel32Base + pINHS->OptionalHeader.DataDirectory[0].VirtualAddress);
DWORD* pAddressOfFunctions = (DWORD*)(dwKernel32Base + pIED->AddressOfFunctions);
DWORD* pAddressOfNames = (DWORD*)(dwKernel32Base + pIED->AddressOfNames);
WORD* pAddressOfNameOrdinals = (WORD*)(dwKernel32Base + pIED->AddressOfNameOrdinals);
int i = 0;
while(1){
// printf("[%d] %s {%d} \n", i, dwKernel32Base+pAddressOfNames[i], pAddressOfNameOrdinals[i]);
/*
if (strcmp(sGetProcAddr, (char*)(dwKernel32Base + pAddressOfNames[i]))==0){
//puts("found"); // 找到对应在序号表的第i个位置
break;
}
*/
// 手动编写strcmp
char* tmp = (char*)(dwKernel32Base + pAddressOfNames[i]);
int index = 0;
int length = 0;
while(sGetProcAddr[index] != '\0'){ // 计算长度
index ++;
}
length = index;
for (index = 0; index < length; index ++){ // 对比
if (sGetProcAddr[index] != tmp[index]){
break;
}
}
if (index == length){ // 找到了
// puts("found"); // 找到对应在序号表的第i个位置
break;
}
// 下一个条目
i ++;
}
i = pAddressOfNameOrdinals[i];
//printf("i=%d in AddressOfFunctions = 0x%p \n", i, dwKernel32Base + pAddressOfFunctions[i]);
PGETPROCADDRESS pGetProcAddress = (PGETPROCADDRESS)(dwKernel32Base + pAddressOfFunctions[i]);
PLOADLIBRARY pLoadLibrary = (PLOADLIBRARY)pGetProcAddress((HMODULE)dwKernel32Base, sLoadLibraryA);
//printf("loadlibrary: 0x%p \n", pLoadLibrary);
HMODULE hUser32DLL = pLoadLibrary(sUser32Dll);
PMESSAGEBOXA pMessageBoxA = (PMESSAGEBOXA)pGetProcAddress(hUser32DLL, sMessageBoxA);
char sHeader[] = {'M', 'z', '1', 0};
char sText[] = {'i', 'n', 'j', 'e', 'c', 't', 'e', 'd', 0};
pMessageBoxA(0,sText ,sHeader,0);
}
int main(){
shellcode();
return 0;
}
本文来自博客园,作者:Mz1,转载请注明原文链接:https://www.cnblogs.com/Mz1-rc/p/18474488
如果有问题可以在下方评论或者email:mzi_mzi@163.com