简单说一下我改造后的shellcode的功能,这是一个通用的弹出一个messagebox的窗口,
通过PEB的方式找到kernel32.dll的基址,再通过计算函数名的HASH值,到kernel32.dll的导出表找出对应的函数的地址,我要找的函数有LoadLibraryA,GetModuleHandleA,ExitProcess,要用GetModuleHandleA是因为查询该进程是否装载了动态库user32.dll,如果装载了就不用LoadLibraryA装载了user32.dll了,不然会出错的,通过GetModuleHandleA可以找出已经装载的user32.dll库的基址,然后通过MessageBoxA的HASH值找到user32.dll导出表中的MessageBoxA函数地址。执行MessageBoxA弹出窗口后,利用ExitProcess退出程序。
__asm
{
MsgPop:
jmp startup_bnc // Jump to the startup bounce point
#include "generic.c"
startup_bnc:
jmp startup // Jump to the real startup
resolve_symbols_for_dll:
lodsd // Load the current dword from esi into eax
push eax // Push the hash as the second argument to find_function
push edx // Push the base address of the current dll being loaded from
call find_function // Call find_function
mov [edi], eax // Store the return address in the current output buffer pointer
add esp, 0x08 // Restore eight bytes to the stack.
add edi, 0x04 // Add 4 bytes to the output buffer to move to the next slot
cmp esi, ecx // Have we reached the end?
jne resolve_symbols_for_dll // If not, continue loading
resolve_symbols_for_dll_finished:
ret // Return to the caller
kernel32_symbol_hashes:
EMIT_4_LITTLE_ENDIAN(0x8e,0x4e,0x0e,0xec) // LoadLibraryA [0x04]
EMIT_4_LITTLE_ENDIAN(0x04,0x49,0x32,0xD3) //GetModuleHandleA
EMIT_4_LITTLE_ENDIAN(0x7e,0xd8,0xe2,0x73) // ExitProcess [0x08]
ws2_32_symbol_hashes:
EMIT_4_LITTLE_ENDIAN(0xA8,0xA2,0x4D,0xBC) //MessageBoxA [0x0c]
startup:
sub esp, 0x60 // Allocate 0x60 bytes of stack space
mov ebp, esp // Use ebp as the frame pointer
jmp get_absolute_address_forward // Jump forward past the middle
get_absolute_address_middle:
jmp get_absolute_address_end // Jump to the end now that we have our VMA on the stack
get_absolute_address_forward:
call get_absolute_address_middle // Call to the middle to push the VMA of 'pop esi' onto the stack
get_absolute_address_end:
pop esi // Pop the return address from the stack into esi
call find_kernel32 // Find the kernel32.dll base address through whatever means
mov edx, eax // Save the kernel32.dll base address in edx
resolve_kernel32_symbols:
sub esi, 0x1e // Offset esi 0x36 bytes back from 'pop esi'
lea edi, [ebp + 0x04] // Set edi to the start of our output buffer
mov ecx, esi // Set ecx to the address of the first hash
add ecx, 0x0c // Set the stop point to the first hash address + 0x10
call resolve_symbols_for_dll // Resolve all the kernel32.dll symbols
xor eax, eax // Zero eax
mov ax, 0x3233 // Set the low order bytes of eax to '32'
push eax // Push '32\0\0'
push 0x72657375 // Push 'user'
mov ebx, esp // Save the pointer to the 'user32' string in ebx
push ecx // Save ecx so that it does not get clobbered
push edx // Save edx so that it does not get clobbered
push ebx // Push the 'user32' string pointer onto the stack
call [ebp + 0x08]
pop edx // Restore edx
pop ecx
test eax,eax
jne IsLoaded
resolve_user32_symbols:
add ecx,0x04
xor eax, eax // Zero eax
mov ax, 0x3233 // Set the low order bytes of eax to '32'
push eax // Push '32\0\0'
push 0x72657375 // Push 'user'
mov ebx, esp // Save the pointer to the 'user32' string in ebx
push ecx // Save ecx so that it does not get clobbered
push edx // Save edx so that it does not get clobbered
push ebx // Push the 'user32' string pointer onto the stack
call [ebp + 0x04] // Call LoadLibraryA
pop edx // Restore edx
pop ecx // Restore ecx
mov edx, eax // Set edx to the base address of user32.dll
call resolve_symbols_for_dll // Resolve all the user32.dll symbols