吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5219|回复: 9
收起左侧

[其他原创] 【汇编】通过汇编获得GetProcAddress函数地址

  [复制链接]
小俊 发表于 2017-12-12 20:18
本帖最后由 wushaominkk 于 2018-8-2 14:39 编辑

[Asm] 纯文本查看 复制代码
.386
.model flat,stdcall
option casemap:none

.code
main:
        push ebp
        mov ebp,esp
        sub esp,10h
        ;------------------------------------------------------
        ;mov ebx,fs:[30]     ;进入OEP的时候,ebx默认是PEB
        mov ebx,[ebx+0Ch]
        mov ebx,[ebx+0Ch]
        mov ebx,[ebx]
        mov ebx,[ebx]
        mov ebx,[ebx+18h]    ;Ebx = kernel32.dll模块基址
        mov eax,[ebx+3Ch]    ;Eax = NtHeader offset
        add eax,ebx          ;NtHeader offset=>VA
        mov eax,[eax+78h]    ;Eax = 导出表RVA
        add eax,ebx          ;导出表RVA=>VA
        mov edx,[eax+20h]    ;Edx = 名称表RVA
        add edx,ebx          ;名称表RVA=>VA
        xor ecx,ecx          ;Ecx清零
MyLoop:
        mov esi,[edx+ecx*4]  ;Esi = 函数名RVA
        add esi,ebx          ;函数名RVA=>VA
        inc ecx              ;Ecx++
        ;0  3   7
        ;GetProcAddress
        movzx edi,byte ptr[esi]   ;取函数名第0个字节
        cmp edi,'G'  ;如果等于ZF会被置为1
        jnz MyLoop   ;ZF为0则跳转
        movzx edi,byte ptr[esi+3] ;取函数名第3个字节
        cmp edi,'P'
        jnz MyLoop
        movzx edi,byte ptr[esi+7] ;取函数名第7个字节
        cmp edi,'A'
        jnz MyLoop
        ;到了这,说明已经找到了GetProcAddress在名称表中的位置了
        ;注意:Ecx现在等于真正的下标+1,而不是真正的下标
        dec ecx ;Ecx减一,才是真正的下标
        mov edx,[eax+24h]   ;Edx = 序号表RVA
        add edx,ebx         ;序号表RVA=>VA
        movzx ecx,word ptr[edx+ecx*2] ;通过序号表找到地址表下标
        mov edx,[eax+1Ch]   ;Edx = 地址表RVA
        add edx,ebx         ;地址表RVA=>VA
        mov esi,[edx+ecx*4] ;函数RVA
        add esi,ebx         ;函数RVA=>VA
        mov [ebp-4],ebx  ;保存kernel32.dll模块基址
        mov [ebp-8],esi  ;保存GetProcAddress函数地址
        call PushStr1    ;将下面的数据入栈
        db "LoadLibraryA",0   ;参数2
PushStr1:
        push [ebp-4]          ;参数1
        call dword ptr[ebp-8] ;GetProcAddress
        mov [ebp-0Ch],eax     ;保存LoadLibraryA函数地址
        call PushStr2         ;将下面的数据入栈
        db "user32.dll",0     ;参数1
PushStr2:
        call eax ;LoadLibraryA
        mov [ebp-10h],eax     ;保存user32.dll模块基址
        ;------------------------------------------------------
        add esp,10h
        pop ebp
        ret
end main


版本2
[Asm] 纯文本查看 复制代码
.386
.model flat,stdcall
option casemap:none
assume fs:nothing

;[+0]   本模块实例句柄
;[+4]   kernel32.dll   模块基址
;[+8]   GetProcAddress 函数地址
;[+0Ch] LoadLibraryA   函数地址
;[+10h] user32.dll     模块基址

.code
main:
        push ebp
        mov ebp,esp
        call GetGlobal
        mov edi,eax
        ;----------------------------------------------
        ;mov ebx,fs:[30h]
        mov ebx,[ebx+0Ch]
        mov ebx,[ebx+0Ch]
        mov edx,[ebx+18h]
        mov [edi],edx     ;[+0]保存本模块实例句柄
        mov ebx,[ebx]
        mov ebx,[ebx]
        mov ebx,[ebx+18h]
        mov [edi+4],ebx   ;[+4]保存kernel32.dll模块基址
        mov eax,[ebx+3Ch] ;取Nt头文件偏移
        add eax,ebx       ;offset=>VA
        mov eax,[eax+78h] ;取导出表RVA
        add eax,ebx       ;RVA=>VA
        mov edx,[eax+20h] ;取名称表RVA
        add edx,ebx       ;RVA=>VA
        xor ecx,ecx       ;ecx清零
        MyLoop:
        mov esi,[edx+ecx*4]   ;取函数名RVA
        add esi,ebx           ;RVA=>VA
        inc ecx               ;ecx++
        cmp byte ptr[esi],'G' ;如果等于ZF会被置为1
        jnz MyLoop            ;ZF为0则跳转
        cmp byte ptr[esi+3],'P'
        jnz MyLoop
        cmp byte ptr[esi+7],'A'
        jnz MyLoop
        dec ecx             ;ecx-- 真正的下标
        mov edx,[eax+24h]   ;取序号表RVA
        add edx,ebx         ;RVA=>VA
        mov cx,[edx+ecx*2]  ;通过序号表找到地址表下标
        mov edx,[eax+1Ch]   ;取地址表RVA
        add edx,ebx         ;RVA=>VA
        mov esi,[edx+ecx*4] ;取函数RVA
        add esi,ebx         ;RVA=>VA
        mov [edi+8],esi     ;保存GetProcAddress函数地址
        call PushStr1       ;将下面的数据地址入栈
        db "LoadLibraryA",0 ;参数2:要获取的函数名
        PushStr1:
        push ebx            ;参数1:kernel32.dll模块基址
        call esi            ;GetProcAddress
        mov [edi+0Ch],eax   ;保存LoadLibraryA函数地址
        call PushStr2       ;将下面的数据地址入栈
        db "user32.dll",0   ;参数1:需要Load的DLL名称
        PushStr2:
        call eax            ;LoadLibraryA
        mov [edi+10h],eax   ;保存user32.dll模块基址
        ;----------------------------------------------
        pop ebp
        ret
GetGlobal:
        mov eax,[esp]
        and eax,0FFFFF000h
        add eax,200h
        ret
end main


加强版:
[Asm] 纯文本查看 复制代码
.386
.model flat,stdcall
option casemap:none
assume fs:nothing

;[+0]   本模块实例句柄
;[+4]   kernel32.dll      模块基址
;[+8]   GetProcAddress    函数地址
;[+0Ch] LoadLibraryA      函数地址
;[+10h] user32.dll        模块基址
;[+14h] ClassName
;[+18h]~[+3Ch] WNDCLASSA  结构体
;[+40h] RegisterClassA    函数地址
;[+44h] DefWindowProcA    函数地址
;[+48h] CreateWindowExA   函数地址
;[+4Ch] GetMessageA       函数地址
;[+50h] DispatchMessageA  函数地址
;[+54h]~[+60h] MSG        结构体
;[+64h] 窗口句柄

.code
main:
        push ebp
        mov ebp,esp
        call GetGlobal
        mov edi,eax
        ;----------------------------------------------------
        ;mov ebx,fs:[30h]
        mov ebx,[ebx+0Ch]
        mov ebx,[ebx+0Ch]
        mov edx,[ebx+18h]
        mov [edi],edx     ;[+0]保存本模块实例句柄
        mov ebx,[ebx]
        mov ebx,[ebx]
        mov ebx,[ebx+18h]
        mov [edi+4],ebx   ;[+4]保存kernel32.dll模块基址
        mov eax,[ebx+3Ch] ;取Nt头文件偏移
        add eax,ebx       ;offset=>VA
        mov eax,[eax+78h] ;取导出表RVA
        add eax,ebx       ;RVA=>VA
        mov edx,[eax+20h] ;取名称表RVA
        add edx,ebx       ;RVA=>VA
        xor ecx,ecx       ;ecx清零
        MyLoop:
        mov esi,[edx+ecx*4]   ;取函数名RVA
        add esi,ebx           ;RVA=>VA
        inc ecx               ;ecx++
        cmp byte ptr[esi],'G' ;如果等于ZF会被置为1
        jnz MyLoop            ;ZF为0则跳转
        cmp byte ptr[esi+3],'P'
        jnz MyLoop
        cmp byte ptr[esi+7],'A'
        jnz MyLoop
        dec ecx             ;ecx-- 真正的下标
        mov edx,[eax+24h]   ;取序号表RVA
        add edx,ebx         ;RVA=>VA
        mov cx,[edx+ecx*2]  ;通过序号表找到地址表下标
        mov edx,[eax+1Ch]   ;取地址表RVA
        add edx,ebx         ;RVA=>VA
        mov esi,[edx+ecx*4] ;取函数RVA
        add esi,ebx         ;RVA=>VA
        mov [edi+8],esi     ;保存GetProcAddress函数地址
        call PushStr1       ;将下面的数据地址入栈
        db "LoadLibraryA",0 ;参数2:要获取的函数名
        PushStr1:
        push ebx            ;参数1:kernel32.dll模块基址
        call esi            ;GetProcAddress
        mov [edi+0Ch],eax   ;保存LoadLibraryA函数地址
        call PushStr2       ;将下面的数据地址入栈
        db "user32.dll",0   ;参数1:需要Load的DLL名称
        PushStr2:
        call eax            ;LoadLibraryA
        mov [edi+10h],eax   ;保存user32.dll模块基址
        
        mov dword ptr[edi+14h],434241h ;ClassName "ABC"
        
        mov dword ptr[edi+18h],0       ;style
        mov dword ptr[edi+1Ch],WndProc ;lpfnWndProc
        mov dword ptr[edi+20h],0       ;cbClsExtra
        mov dword ptr[edi+24h],0       ;cbWndExtra
        mov edx,[edi]                  ;取实例句柄
        mov dword ptr[edi+28h],edx     ;hInstance
        mov dword ptr[edi+2Ch],0       ;hIcon
        mov dword ptr[edi+30h],0       ;hCursor
        mov dword ptr[edi+34h],0       ;hbrBackground
        mov dword ptr[edi+38h],0       ;lpszMenuName
        lea edx,[edi+14h]              ;取字符串地址
        mov dword ptr[edi+3Ch],edx     ;lpszClassName
        
        call PushStr3         ;将下面的数据地址入栈
        db "RegisterClassA",0 ;参数2:要获取的函数名
        PushStr3:
        push [edi+10h]        ;参数1:user32.dll模块基址
        call esi              ;GetProcAddress
        mov [edi+40h],eax     ;保存RegisterClassA函数地址
        lea edx,[edi+18h]     ;取WNDCLASSA结构体地址
        push edx              ;参数1:&WNDCLASSA
        call eax              ;RegisterClassA
        
        call PushStr4         ;将下面的数据地址入栈
        db "DefWindowProcA",0 ;参数2:要获取的函数名
        PushStr4:
        push [edi+10h]        ;参数1:user32.dll模块基址
        call esi              ;GetProcAddress
        mov [edi+44h],eax     ;保存DefWindowProcA函数地址
        
        call PushStr5          ;将下面的数据地址入栈
        db "CreateWindowExA",0 ;参数2:要获取的函数名
        PushStr5:
        push [edi+10h]         ;参数1:user32.dll模块基址
        call esi               ;GetProcAddress
        mov [edi+48h],eax      ;保存CreateWindowExA函数地址
        
        push 0                 ;lpParam
        push [edi]             ;hInstance
        push 0                 ;hMenu
        push 0                 ;hWndParent
        push 200               ;nHeight
        push 400               ;nWidth
        push 0                 ;Y
        push 0                 ;X
        push 10080000h         ;dwStyle
        push 0                 ;lpWindowName
        lea edx,[edi+14h]      ;取字符串地址
        push edx               ;lpClassName
        push 00000010h         ;dwExStyle
        call eax               ;CreateWindowExA
        mov [edi+64h],eax      ;保存窗口句柄
        
        call CreateControl     ;创建控件
        
        call PushStr6           ;将下面的数据地址入栈
        db "GetMessageA",0      ;参数2:要获取的函数名
        PushStr6:
        push [edi+10h]          ;参数1:user32.dll模块基址
        call esi                ;GetProcAddress
        mov [edi+4Ch],eax       ;保存GetMessageA函数地址
        
        call PushStr7           ;将下面的数据地址入栈
        db "DispatchMessageA",0 ;参数2:要获取的函数名
        PushStr7:
        push [edi+10h]          ;参数1:user32.dll模块基址
        call esi                ;GetProcAddress
        mov [edi+50h],eax       ;保存DispatchMessageA函数地址
        
        MsgLoop:
        call GetGlobal
        mov edi,eax
        push 0
        push 0
        push 0
        lea edx,[edi+54h]
        push edx
        call dword ptr[edi+4Ch]
        lea edx,[edi+54h]
        push edx
        call dword ptr[edi+50h]
        jmp        MsgLoop
        ;----------------------------------------------------
        pop ebp
        ret
WndProc:
        push ebp
        mov ebp,esp
        call GetGlobal
        mov edi,eax
        ;------------------------------------------
        push [ebp+14h]
        push [ebp+10h]
        push [ebp+0Ch]
        push [ebp+08h]
        call dword ptr[edi+44h]
        ;------------------------------------------
        pop ebp
        ret 10h
CreateControl:
        call GetGlobal
        mov edi,eax
        push 0                 ;lpParam
        push [edi]             ;hInstance
        push 1                 ;hMenu
        push [edi+64h]         ;hWndParent
        push 20                ;nHeight
        push 100               ;nWidth
        push 0                 ;Y
        push 0                 ;X
        push 50800000h         ;dwStyle
        push 0                 ;lpWindowName
        call PushStr10
        db "Edit",0          ;lpClassName
        PushStr10:
        push 0                 ;dwExStyle
        call dword ptr[edi+48h] ;CreateWindowExA
        ret
GetGlobal:
        mov eax,[esp]
        and eax,0FFFFF000h
        add eax,400h
        ret
end main

免费评分

参与人数 3吾爱币 +3 热心值 +3 收起 理由
565266718 + 1 + 1 谢谢@Thanks!
qaz003 + 1 + 1 用心讨论,共获提升!
kendling + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 小俊 发表于 2017-12-12 20:42
ShellCode
[Asm] 纯文本查看 复制代码
8B 5B 0C 8B 5B 0C 8B 1B 8B 1B 8B 5B 18 8B 43 3C
03 C3 8B 40 78 03 C3 8B 50 20 03 D3 33 C9 8B 34
8A 03 F3 41 0F B6 3E 83 FF 47 75 F2 0F B6 7E 03
83 FF 50 75 E9 0F B6 7E 07 83 FF 41 75 E0 49 8B
50 24 03 D3 0F B7 0C 4A 8B 50 1C 03 D3 8B 34 8A
03 F3 8B FB C3
XC_蛋蛋君 发表于 2017-12-12 20:46
hbe 发表于 2017-12-12 20:57 来自手机
qaz003 发表于 2017-12-12 21:35
谢谢分享。。注释得很祥细。。。
寒尘丶Coldust 发表于 2017-12-12 23:34
很详细 不过具体用的话 还是得像shellcode那样比较精简
chen4321 发表于 2017-12-13 08:19 来自手机
说的很明白,谢谢分享
XT0624 发表于 2017-12-13 09:26
厉害阿 老哥
565266718 发表于 2018-2-6 09:01
支持。。。。。
Adrian_07 发表于 2018-8-2 14:24
谢谢分享!!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 15:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表