首页
社区
课程
招聘
[旧帖] [原创]自己用汇编实现GetProcAdress函数 0.00雪花
发表于: 2011-9-13 08:33 1999

[旧帖] [原创]自己用汇编实现GetProcAdress函数 0.00雪花

2011-9-13 08:33
1999
在弄外壳,打算自己实现GetProcAdress函数。下面是该函数的汇编代码,支持函数名和序号。
自己测试成功,不论通过函数名还是通过序号都可以成功获取指定函数。但在使用该函数恢复输入表时,总是出错,不晓得哪里除了问题。是代码有错,还是和函数转发器有关系?
;========================================================================
;下面为外壳自带的GetProcAddress函数
;========================================================================
MyGetApi                proc        _hModule,_lpszApi
                local        @dwReturn,@dwStringLength

                pushad
                mov        @dwReturn,0

;********************************************************************
; 计算 API 字符串的长度(带尾部的0)
;********************************************************************
                mov        edi,_lpszApi
        
                cmp edi,0FFFFh      ;如果是按序号导入
                jg IsFunName

        mov        esi,_hModule
                add        esi,[esi + 3ch]
                assume        esi:ptr IMAGE_NT_HEADERS
                mov        esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
                add        esi,_hModule
                assume        esi:ptr IMAGE_EXPORT_DIRECTORY

                sub edi,[esi].nBase
                shl        edi,2
                add        edi,[esi].AddressOfFunctions
                add        edi,_hModule

                mov        eax,[edi]
                add        eax,_hModule
                mov        @dwReturn,eax
                jmp _Error

IsFunName:
                mov        ecx,-1
                xor        al,al       ;al清零。xor: 1 xor 1=0,0 xor 0=0,1 xor 0=1,0 xor 1=1
                cld
                repnz        scasb   ;( AL ) - (( DI )),   ( DI ) ← ( DI ) ± 1
                mov        ecx,edi
                sub        ecx,_lpszApi
                mov        @dwStringLength,ecx
;********************************************************************
; 从 PE 文件头的数据目录获取导出表地址
;********************************************************************
        assume        esi:nothing

        mov        esi,_hModule
                add        esi,[esi + 3ch]
                assume        esi:ptr IMAGE_NT_HEADERS
                mov        esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
                add        esi,_hModule
                assume        esi:ptr IMAGE_EXPORT_DIRECTORY
;********************************************************************
; 查找符合名称的导出函数名
;********************************************************************

                mov        ebx,[esi].AddressOfNames
                add        ebx,_hModule
                xor        edx,edx
                .repeat
                        push        esi    ;保存esi
                        mov        edi,[ebx]
                        add        edi,_hModule
                        mov        esi,_lpszApi
                        mov        ecx,@dwStringLength
                        repz        cmpsb
                        .if        ZERO?
                                pop        esi
                                jmp        @F
                        .endif
                        pop        esi
                        add        ebx,4
                        inc        edx
                .until        edx >=        [esi].NumberOfNames
                jmp        _Error
@@:
;********************************************************************
; API名称索引 --> 序号索引 --> 地址索引
;********************************************************************
                sub        ebx,[esi].AddressOfNames
                sub        ebx,_hModule
                shr        ebx,1              ;ebx = 序号索引, AddressOfNameOrdinals是WORD型数组,AddressOfFunctions是DWORD数组,所以除以2
                add        ebx,[esi].AddressOfNameOrdinals
                add        ebx,_hModule       ;ebx = 指定函数的序号的地址
                movzx        eax,word ptr [ebx]  
                shl        eax,2
                add        eax,[esi].AddressOfFunctions
                add        eax,_hModule
;********************************************************************
; 从地址表得到导出函数地址
;********************************************************************
                mov        eax,[eax]
                add        eax,_hModule
                mov        @dwReturn,eax
_Error:
                ;pop        fs:[0]
                ;add        esp,0ch
                assume        esi:nothing
                popad
                mov        eax,@dwReturn
                ret

MyGetApi endp

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (5)
雪    币: 90
活跃值: (82)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
是被加壳的程序崩溃,正在找原因...

应该和这个函数有某些关系。
2011-9-13 08:39
0
雪    币: 349
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
mov  edi,_lpszApi
cmp edi,0FFFFh      ;如果是按序号导入
    jg IsFunName
这里没看懂,你这样赋值,edi不是等于0x0012xxxx么?
2011-9-13 09:19
0
雪    币: 90
活跃值: (82)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
mov  edi,_lpszApi
cmp edi,0FFFFh      ;如果是按序号导入
    jg IsFunName
这里没看懂,你这样赋值,edi不是等于0x0012xxxx么?
======================================
没有赋值啊,你看错了吧?
_lpszApi是函数参数,只是进行比较,如果大于 ffffh这个常数,就说明该参数指向函数名。
否则,该参数指向函数序号。
2011-9-13 10:09
0
雪    币: 90
活跃值: (82)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
没有赋值啊,你看错了吧?
_lpszApi是函数参数,只是进行比较,如果大于 ffffh这个常数,就说明该参数指向函数名。
否则,该参数就是函数序号。

不是指向,对不起。
2011-9-13 10:13
0
雪    币: 90
活跃值: (82)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
是函数转发器的问题,代码需要支持函数转发器。
2011-9-15 02:33
0
游客
登录 | 注册 方可回帖
返回
//