ShellCode: 00981000 8B 00 mov eax,dword ptr [eax] 00981002 EB 02 jmp shellcode_start (981006h) 00981004 90 nop 00981005 90 nop shellcode_start: 00981006 55 push ebp
ShellCode: 01121000 8B 00 mov eax,dword ptr [eax] 01121002 E8 02 00 00 00 call shellcode_start (1121009h) 01121007 90 nop 01121008 90 nop shellcode_start: 01121009 55 push ebp
void _declspec(naked)ShellCode()
{
#define LoadLibraryExA_Digest 0xc0d83287
#define LoadLibraryA_Digest 0x0C917432
#define MessageBoxA_Digest 0x1E380A6A
#define FreeLibrary_Digest 0x30BA7C8C
__asm
{
shellcode_start:
push ebp // 保存栈帧
mov ebp, esp
// 在栈中构造UNICODE字符串 KERNEL32.DLL[K\0E\0 R\0N\0 E\0L\0 3\02\0 .\0D\0 L\0L\0 \0\0\0\0
push 0000000h //0000
push 004C004Ch //0L0L
push 0044002Eh //0D0.
push 00320033h //0203
push 004c0045h //0L0E
push 004E0052h //ONOR
push 0045004Bh //0E0K
push esp
call get_module_base
add esp, 7*4
test eax, eax
jz _shellcode_return
push eax // [ebp-4]
push LoadLibraryA_Digest
push eax
call get_proc_address_by_digest
test eax, eax
jz _shellcode_return
// 在栈中构造ANSI字符串 USER32.DLL
push 00004C4Ch //‘00LL‘
push 442E3233h //‘D.23‘
push 52455355h //‘RESU‘
push esp
call eax // LoadLibraryA
add esp, 3*4
test eax, eax
jz _shellcode_return
push eax // [ebp-8] hModule
push MessageBoxA_Digest
push eax
call get_proc_address_by_digest
test eax, eax
jz _shellcode_return
// 在栈中构造ANSI字符串 Shell Code. Shion [Shel l_Co de._ Shio n000
mov edi, ‘000n‘
and edi, 000000ffh
push edi
push ‘oihS‘
push ‘ .ed‘
push ‘oC l‘
push ‘lehS‘
mov edi, esp
push 00000040h
push 0
push edi
push 0
call eax
add esp, 5*4
push FreeLibrary_Digest
mov edi, [ebp-4]
push edi
call get_proc_address_by_digest
test eax, eax
jz _shellcode_return
push [ebp-8]
call eax
_shellcode_return:
mov esp, ebp
pop ebp // 恢复栈帧
ret
/************************************************************************/
/* Get base address of module
* tishion
* 2013-05-26 13:45:20
* IN:
* ebp+8 = moudule name null-terminate string [WCHAR]
*
* OUT:
* eax = ntdll.base
* #define _Wcsnicmp_Digest 0x548b2e5f
/************************************************************************/
get_module_base:
push ebp
mov ebp, esp
call get_ntdll_base
test eax, eax
jz _find_modulebase_done
push 548b2e5fh
push eax
call get_proc_address_by_digest
test eax, eax // _wcsnicmp
jz _find_modulebase_done
push eax // [ebp-04h]_wcsnicmp
mov eax, fs:[30h] // eax = ppeb
test eax, eax
jz _find_modulebase_done
mov eax, [eax+0ch] // eax = pLdr pLdr:[PEB_LDR_DATA]
test eax, eax
jz _find_modulebase_done
mov esi, [eax+1ch]
jmp _compare_moudule_name
_find_modulebase_loop:
mov esi, [esi] // esi = pLdr->InInitializationOrderModuleList
_compare_moudule_name:
test esi, esi
jz _find_modulebase_done
xor edi, edi
mov di, word ptr[esi+1ch] // length
push edi
push [esi+20h] // pLdrDataTableEntry.DllBaseName.Buffer [WCHAR]
push [ebp+08h]
mov edi, [ebp-04h]
call edi
test eax, eax
jnz _find_modulebase_loop
mov eax, [esi+08h] // eax = pLdrDataTableEntry.DllBase
//mov ecx, [esi+20h]
_find_modulebase_done:
mov esp, ebp
pop ebp
ret 4
/************************************************************************/
/* Get base address of ntdll.dll module
* tishion
* 2013-05-26 13:45:20
*
* OUT:
* eax = ntdll.base
/************************************************************************/
get_ntdll_base:
mov eax, fs:[30h] // eax = ppeb
test eax, eax
jz _find_ntdllbase_done
mov eax, [eax+0ch] // eax = pLdr pLdr:[PEB_LDR_DATA]
test eax, eax
jz _find_ntdllbase_done
mov eax, [eax+1ch] // eax = pLdr->InInitializationOrderModuleList
test eax, eax
jz _find_ntdllbase_done
mov eax, [eax+08h] // eax = pLdrDataTableEntry.DllBase
_find_ntdllbase_done:
ret
/************************************************************************/
/* Get function name digest
* tishion
* 2013-05-26 13:45:20
*
* IN:
* esi = function name
* OUT:
* edx = digest
/************************************************************************/
get_ansi_string_digest:
push eax
xor edx, edx
_next_char:
xor eax, eax
lodsb
test eax, eax
jz _done
ror edx, 7
add edx, eax
jmp _next_char
_done:
pop eax
ret
/************************************************************************/
/* Get function address by searching export table
* tishion
* 2013-05-26 13:50:13
*
* IN:
* [ebp+8] = module base
* [ebp+0ch] = function name digest
* OUT:
* eax function address (null if failed)
/************************************************************************/
get_proc_address_by_digest:
push ebp
mov ebp, esp
mov eax, [ebp+8]
cmp word ptr [eax], 5a4dh // ‘MZ‘
jnz _return_null
add eax, [eax+3ch] // eax = ImageNtHeader IMAGE_NT_HEADERS
cmp dword ptr [eax], 00004550h // ‘PE‘
jnz _return_null
push eax // [ebp-04h]
//add eax, 18h // eax = ImageOptionalHeader IMAGE_OPTIONAL_HEADER
//add eax, 60h // eax = ImageExportDirectoryEntry IMAGE_DIRECTORY_ENTRY_EXPORT
// 以上两行只是为了让程序流程清晰,为了减小代码长度,合并两条指令为一条,如下:
add eax, 78h
mov eax, [eax] // eax = RVA IMAGE_EXPORT_DIRECTORY
add eax, [ebp+08h] // eax = ImageExportDirectory IMAGE_EXPORT_DIRECTORY
mov ecx, eax
mov eax, [ecx+20h]
add eax, [ebp+08h] // eax = AddressOfNames
push eax // [ebp-08h] 导出名称地址表
mov eax, [ecx+24h]
add eax, [ebp+08h] // eax = AddressOfNameOrdinals
push eax // [ebp-0ch] 导出序号表
mov eax, [ecx+1ch]
add eax, [ebp+08h] // eax = AddressOfFunctions
push eax // [ebp-10h] 导出RAV地址表
mov eax, [ecx+10h] // ordinals base
push eax // [ebp-14h]
mov eax, [ecx+14h] // NumberOfFunctions
push eax // [ebp-18h]
mov eax, [ecx+18h] // NumberOfNames
push eax // [ebp-1ch]
mov ecx, [ebp-1ch]
mov ebx, ecx
mov eax, [ebp-08h]
_find_func:
mov edi, ebx
sub edi, ecx
mov esi, [eax+edi*4]
test esi, esi // esi是否NULL
loope _find_func
inc ecx
add esi, [ebp+08h]
call get_ansi_string_digest
cmp edx, [ebp+0ch]
loopne _find_func // ecx 为目标函数在函数名数组中的index
xor edx, edx
mov eax, [ebp-0ch]
mov dx, [eax+edi*2]
//add edx, [ebp-14h] //Ordinal base 处理, 蛋疼?找微软!
//sub edx, [ebp-14h]
// 以上两条同样是让程序流程清晰,实际运用中,如果不需要输出Ordinal,则不需要进行该操作
cmp edx, [ebp-18h]
jae _return_null
mov eax, [ebp-10h] // eax = AddressOfFunctions
mov eax, [eax+edx*4] // edi = RVA地址数组的地址 edi+4*序号 即为 某一函数的RVA地址
add eax, [ebp+08h]
jmp _function_found_done
_return_null:
xor eax, eax
_function_found_done:
mov esp, ebp
pop ebp
ret 8
//jmp_to_oep:
// //jmp $
// jmp _tWinMain
}
}
LoadLibraryExA_Digest equ 0xc0d83287 LoadLibraryA_Digest equ 0x0C917432 MessageBoxA_Digest equ 0x1E380A6A FreeLibrary_Digest equ 0x30BA7C8C use32 shellcode_start: push ebp ;// 保存栈帧 mov ebp, esp ;// 在栈中构造UNICODE字符串 KERNEL32.DLL[K\0E\0 R\0N\0 E\0L\0 3\02\0 .\0D\0 L\0L\0 \0\0\0\0 push 00000000h ;//0000 push 004C004Ch ;//0L0L push 0044002Eh ;//0D0. push 00320033h ;//0203 push 004c0045h ;//0L0E push 004E0052h ;//0N0R push 0045004Bh ;//0E0K push esp call get_module_base add esp, 7*4 test eax, eax jz ._shellcode_return push eax ;// [ebp-4] push LoadLibraryA_Digest push eax call get_proc_address_by_digest test eax, eax jz ._shellcode_return ;// 在栈中构造ANSI字符串 USER32.DLL ;push 00004C4Ch ;//‘00LL‘ ;push 442E3233h ;//‘D.23‘ ;push 52455355h ;//‘RESU‘ push ‘LL‘ push ‘32.D‘ push ‘USER‘ push esp call eax ;// LoadLibraryA add esp, 3*4 test eax, eax jz ._shellcode_return push eax ;// [ebp-8] hModule push MessageBoxA_Digest push eax call get_proc_address_by_digest test eax, eax jz ._shellcode_return ;// 在栈中构造ANSI字符串 Shell Code. Shion [Shel l_Co de._ Shio n000 push ‘ion‘ push ‘Tish‘ push ‘de. ‘ push ‘l Co‘ push ‘Shel‘ mov edi, esp push 00000040h push 0 push edi push 0 call eax add esp, 5*4 push FreeLibrary_Digest push dword [ebp-4] call get_proc_address_by_digest test eax, eax jz ._shellcode_return push dword [ebp-8] call eax ._shellcode_return: mov esp, ebp pop ebp ;// 恢复栈帧 ret jmp jmp_to_oep ;/************************************************************************/ ;/* Get base address of module ;* tishion ;* 2013-05-26 13:45:20 ;* IN: ;* ebp+8 = moudule name null-terminate string [WCHAR] ;* ;* OUT: ;* eax = ntdll.base ;* #define _Wcsnicmp_Digest 0x548b2e5f ;/************************************************************************/ get_module_base: push ebp mov ebp, esp call get_ntdll_base test eax, eax jz ._find_modulebase_done push 548b2e5fh ;// hash of _wcsnicmp push eax call get_proc_address_by_digest test eax, eax ;// _wcsnicmp jz ._find_modulebase_done push eax ;// [ebp-04h]_wcsnicmp mov eax, 30h mov eax, [fs:eax] ;// eax = ppeb test eax, eax jz ._find_modulebase_done mov eax, [eax+0ch] ;// eax = pLdr pLdr:[PEB_LDR_DATA] test eax, eax jz ._find_modulebase_done mov esi, [eax+1ch] jmp ._compare_moudule_name ._find_modulebase_loop: mov esi, [esi] ;// esi = pLdr->InInitializationOrderModuleList ._compare_moudule_name: test esi, esi jz ._find_modulebase_done xor edi, edi mov di, word [esi+1ch] ;// length push edi push dword [esi+20h] ;// esi = pLdrDataTableEntry.DllBaseName.Buffer [WCHAR] push dword [ebp+08h] mov edi, [ebp-04h] call edi test eax, eax jnz ._find_modulebase_loop mov eax, [esi+08h] ;// eax = pLdrDataTableEntry.DllBase ;//mov ecx, [esi+20h] ._find_modulebase_done: mov esp, ebp pop ebp ret 4 ;/************************************************************************/ ;/* Get base address of ntdll.dll module ;* tishion ;* 2013-05-26 13:45:20 ;* ;* OUT: ;* eax = ntdll.base ;/************************************************************************/ get_ntdll_base: mov eax, 30h mov eax, [fs:eax] ;// eax = ppeb test eax, eax jz ._find_ntdllbase_done mov eax, [eax+0ch] ;// eax = pLdr pLdr:[PEB_LDR_DATA] test eax, eax jz ._find_ntdllbase_done mov eax, [eax+1ch] ;// eax = pLdr->InInitializationOrderModuleList test eax, eax jz ._find_ntdllbase_done mov eax, [eax+08h] ;// eax = pLdrDataTableEntry.DllBase ._find_ntdllbase_done: ret ;/************************************************************************/ ;/* Get function name digest ;* tishion ;* 2013-05-26 13:45:20 ;* ;* IN: ;* esi = function name ;* OUT: ;* edx = digest ;/************************************************************************/ get_ansi_string_digest: push eax xor edx, edx ._next_char: xor eax, eax lodsb test eax, eax jz ._done ror edx, 7 add edx, eax jmp ._next_char ._done: pop eax ret ;/************************************************************************/ ;/* Get function address by searching export table ;* tishion ;* 2013-05-26 13:50:13 ;* ;* IN: ;* [ebp+8] = module base ;* [ebp+0ch] = function name digest ;* OUT: ;* eax function address (null if failed) ;/************************************************************************/ get_proc_address_by_digest: push ebp mov ebp, esp mov eax, [ebp+8] cmp word [eax], 5a4dh ;// ‘MZ‘ jnz ._return_null add eax, [eax+3ch] ;// eax = ImageNtHeader IMAGE_NT_HEADERS cmp dword [eax], 00004550h ;// ‘PE‘ jnz ._return_null push eax ;// [ebp-04h] ;//add eax, 18h ;// eax = ImageOptionalHeader IMAGE_OPTIONAL_HEADER ;//add eax, 60h ;// eax = ImageExportDirectoryEntry IMAGE_DIRECTORY_ENTRY_EXPORT ;// 以上两行只是为了让程序流程清晰,为了减小代码长度,合并两条指令为一条,如下: add eax, 78h mov eax, [eax] ;// eax = RVA IMAGE_EXPORT_DIRECTORY add eax, [ebp+08h] ;// eax = ImageExportDirectory IMAGE_EXPORT_DIRECTORY mov ecx, eax mov eax, [ecx+20h] add eax, [ebp+08h] ;// eax = AddressOfNames push eax ;// [ebp-08h] 导出名称地址表 mov eax, [ecx+24h] add eax, [ebp+08h] ;// eax = AddressOfNameOrdinals push eax ;// [ebp-0ch] 导出序号表 mov eax, [ecx+1ch] add eax, [ebp+08h] ;// eax = AddressOfFunctions push eax ;// [ebp-10h] 导出RAV地址表 push dword [ecx+10h] ;// [ebp-14h]ordinals base push dword [ecx+14h] ;// [ebp-18h]NumberOfFunctions push dword [ecx+18h] ;// [ebp-1ch]NumberOfNames mov ecx, [ebp-1ch] mov ebx, ecx mov eax, [ebp-08h] ._find_func: mov edi, ebx sub edi, ecx mov esi, [eax+edi*4] test esi, esi ;// esi是否NULL loope ._find_func inc ecx add esi, [ebp+08h] call get_ansi_string_digest cmp edx, [ebp+0ch] loopne ._find_func ;// ecx 为目标函数在函数名数组中的index xor edx, edx mov eax, [ebp-0ch] mov dx, [eax+edi*2] ;//add edx, [ebp-14h] ;//Ordinal base 处理, 蛋疼?找微软! ;//sub edx, [ebp-14h] ;// 以上两条同样是让程序流程清晰,实际运用中,如果不需要输出Ordinal,则不需要进行该操作 cmp edx, [ebp-18h] jae ._return_null mov eax, [ebp-10h] ;// eax = AddressOfFunctions mov eax, [eax+edx*4] ;// edi = RVA地址数组的地址 edi+4*序号 即为 某一函数的RVA地址 add eax, [ebp+08h] jmp ._function_found_done ._return_null: xor eax, eax ._function_found_done: mov esp, ebp pop ebp ret 8 jmp_to_oep: jmp $
原文:http://blog.csdn.net/otishiono/article/details/51524424