首页
社区
课程
招聘
[原创]通过散列获取函数地址
发表于: 2009-9-4 19:02 9114

[原创]通过散列获取函数地址

2009-9-4 19:02
9114

介绍:本文不静态引入任何库文件 动态获取kernel32地址
然后查找kernel32的输出表 计算输出函数的散列值与输入的值比较,找到后 查找该函数的序号 最后查找函数地址数组 找到函数地址(这个方法我以前见过,可是现在忘了,于是花了一天时间写了这个代码,这样的代码应该在shellcode中能见到)
程序演示 用LoadLibrary加载user32.dll 然后调用MessageBoxA 这两个函数的输入字符串 都是通过堆栈传递的
汇编很蹩脚大家凑合着看,特别是开始部分(查找kernel32.dll地址) 是早上写的,看了几个小时的书终于会写函数了,所以下午写的代码还像个样子  
如果用ollyice调试可能会出现异常的情况,可能是由于手工编写的原因,下个断点都比较困难,而且ollyice反汇编出来的代码 也不稳定 这应该是ollyice的问题
.386
.model flat,stdcall
option casemap:none
Jisuan proto :DWORD
GetAddr proto :DWORD,:DWORD
.code
start:
        ;xor eax,eax
        ;ret
        MOV EAX,DWORD PTR [ESP]                       ;取得程序返回地址 只要这个地址在kernel32.dll中都可以找到kerner32.dll的基地址
        AND EAX,0FFFF0000H                     ;模块的加载地址64K对齐
        F:
        ;.IF  word ptr [eax] != 'MZ'相反了
        ;NOP
        ;NOP
        ;.ENDIF
        CMP WORD PTR [EAX],5A4DH;MZ
        JNZ NEXT
        MOV EDX,DWORD PTR [EAX+3CH]
        ADD EDX,EAX
        CMP WORD PTR [EDX],4550H;PE
        JE  FINDED
        NEXT:
        DEC EAX
        XOR AX,AX
        CMP EAX,70000000H               
        JA F
        FINDED:                                                        ;找到kernel32的地址
        MOV EBX,EAX;EBX=KERNEL.DLL地址 EDX是PE地址              ;;;;;;;;;;;   
        MOV EAX,[EDX+78H]                                        ;
        ADD EAX,EBX;EAX = IMAGE_EXPORT_DIRECTORY BaseAddress        ;
        MOV ECX,[EAX+10H];[EAX+10] = nBase                        ;测试用
        MOV EDX,[EAX+20H];AddressOfNames                        ;
        MOV EAX,[EBX+EDX];                                        ;       
        LEA EAX,[EBX+EAX];                                        ;;;;;;;;;;;
        ;INVOKE Jisuan,EAX
        INVOKE GetAddr,EBX,0AADF0F1H;LoadLibraryA hash后的值
        PUSH 00006C6CH
        PUSH 642E3233H
        PUSH 52455355H
        MOV  EBX,ESP
        PUSH EBX
        CALL EAX
        ADD ESP,0CH
        INVOKE GetAddr,EAX,078A5C51H;MessageBoxA hash值
        PUSH 00006C6CH
        PUSH 642E3233H
        PUSH 52455355H
        MOV  EBX,ESP
        PUSH 0
        PUSH EBX
        PUSH EBX
        PUSH 0
        CALL EAX
        ADD ESP,0CH
        NOP
        NOP
        NOP
        RET
;;;;;;;;;;;;;;;;;;;;;;;
;;;;Jisuan用于计算指定字符串的hash值
;;;;只有一个字符串地址参数 返回hash值
;;;;;;;;;;;;;;;;;;;;;;;
Jisuan proc pFunName:DWORD;USES EBX,ECX
        ;LOCAL f:BYTE
        PUSH EBX
        PUSH ECX
        PUSH EDX
        XOR EBX,EBX
        ;MOV BL,BYTE PTR [pFunName] 直接用这句是不行滴
        MOV ECX,pFunName
        MOV BL,BYTE PTR [ECX]
        XOR EAX,EAX
        ;XOR ECX,ECX
        .WHILE BL
               
                SHL EAX,4
                ADD EAX,EBX
                XOR EDX,EDX
                MOV EDX,EAX
                AND EDX,0F0000000H
                .IF EDX
               
                        PUSH EDX;保护EDX值
                        SHR EDX,24
                        XOR EAX,EDX
                        POP EDX
                       
                .endif
               
                NOT EDX
                AND EAX,EDX
                INC ECX
                MOV BL,BYTE PTR [ECX]
        .endw
        POP EDX
        POP ECX
        POP EBX
        ret

Jisuan endp
;;;;;;;;;;;;;;;
;BaseAddr模块的加载地址
;ID 函数名hash后的数值
;;;;;;;;;;;;;;;
GetAddr proc uses EBX ECX EDX, BaseAddr:DWORD,ID:DWORD
        LOCAL AddressOfFunction:DWORD,AddressOfNames:DWORD,AddressOfNameOrdinals:DWORD,nBase:DWORD,Num:DWORD
        ;MOV EAX,BaseAddr
        MOV EBX,BaseAddr
        MOV EAX,[EBX+3CH]
        ADD EAX,EBX;获取PEHEADER ADDRESS
        MOV EAX,[EAX+78H]
        ADD EAX,EBX
        MOV EDX,[EAX+10H]
        MOV nBase,EDX
        MOV EDX,[EAX+18H]
        MOV Num,EDX;函数名字总数
        MOV EDX,[EAX+20H]
        MOV AddressOfNames,EDX
        MOV EDX,[EAX+1CH]
        MOV AddressOfFunction,EDX
        MOV EDX,[EAX+24H]
        MOV AddressOfNameOrdinals,EDX
        ;MOV nBase,[EAX+10H];nBase
        ;MOV AddressOfNames,[EAX+20H];AddressOfname
        XOR ECX,ECX
        ;LEA EDX,[EBX+AddressOfNames]不能这样
        MOV EDX,AddressOfNames
        ADD EDX,EBX
        .WHILE ECX < Num
               
                MOV EAX,[EDX+ECX*4]
                ADD EAX,EBX
                INVOKE Jisuan,EAX
                .IF EAX == ID
                        .break
                .endif
                INC ECX
        .endw
        MOV EDX,AddressOfNameOrdinals
        ADD EDX,EBX
        ;.WHILE ECX
        ;        LEA EDX,[EDX+2H]
        ;        DEC ECX
        ;.endw
        XOR EAX,EAX
        MOV AX,[EDX+ECX*2];取得Ordinal
        MOV EDX,AddressOfFunction
        ADD EDX,EBX
        MOV EAX,[EDX+EAX*4];从AddressOfFunction数组查出地址
        ADD EAX,EBX
        ;XOR EAX,EAX
        ret

GetAddr endp
END start
上面计算散列的函数可以用以下代码实现:
#include <stdio.h>
//#define M 0xffffffff
int ELFhash(char *key);
int main(int argc, char* argv[])
{
        printf("Abs:%8x",ELFhash("LoadLibraryA"));
        printf("\n");
        printf("MessageBoxA:%8x",ELFhash("MessageBoxA"));
        return 0;
}
int ELFhash(char *key)
{
        unsigned long h=0;
        while(*key)
        {
                h=(h<<4)+*key++;
                unsigned long g = h& 0xf0000000L;
                if(g) h^=g>>24;
                h &=~g;
        }

        return h;
}


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (14)
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主辛苦了,谢谢
2009-9-4 19:41
0
雪    币: 11198
活跃值: (158)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
Thank you for sharing
2009-9-6 12:08
0
雪    币: 88
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
很老的技术了哇
还是很支持楼主,呵呵
2009-9-6 13:33
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
5
相当老技术啊~
2009-9-6 17:36
0
雪    币: 377
活跃值: (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
6
是啊 真的有点老了 感觉这东西能替代 GetProcAddress
2009-9-6 18:17
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
7
很经典的技术。。。
2009-9-6 19:45
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
8
比不上二分法的速度吧?
2009-9-6 22:10
0
雪    币: 377
活跃值: (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
9
二分法应该是对有序的数据吧
2009-9-6 22:52
0
雪    币: 635
活跃值: (101)
能力值: ( LV12,RANK:420 )
在线值:
发帖
回帖
粉丝
10
输出表本身就是有序的数据,因此二分法最快。楼主的是病毒、木马、SHELLCODE常用的一个非常没意思的算法。
2009-9-7 00:05
0
雪    币: 377
活跃值: (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
11
期待高人指点啊
2009-9-7 00:40
0
雪    币: 104
活跃值: (72)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
12
;xor eax,eax
  ;ret
  MOV EAX,DWORD PTR [ESP]           ;取得程序返回地址 只要这个地址在kernel32.dll中都可以找到kerner32.dll的基地址
  AND EAX,0FFFF0000H                     ;模块的加载地址64K对齐
  F:
  ;.IF  word ptr [eax] != 'MZ'相反了
  ;NOP
  ;NOP
  ;.ENDIF
  CMP WORD PTR [EAX],5A4DH;MZ
  JNZ NEXT
  MOV EDX,DWORD PTR [EAX+3CH]
  ADD EDX,EAX
  CMP WORD PTR [EDX],4550H;PE
  JE  FINDED
  NEXT:
  DEC EAX                                         ;<-----这块有些疑问是不是每次减去64k就可以了~
  XOR AX,AX
  CMP EAX,70000000H   
  JA F
  FINDED:
2009-9-7 09:26
0
雪    币: 377
活跃值: (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
13
[QUOTE=hash;682734];xor eax,eax
  ;ret
  MOV EAX,DWORD PTR [ESP]           ;取得程序返回地址 只要这个地址在kernel32.dll中都可以找到kerner32.dll的基地址
  AND EAX,0FFFF0000H                   ...[/QUOTE]DEC EAX的结果是XXXXFFFF 通过xor ax,ax
变成XXXX0000
2009-9-7 12:44
0
雪    币: 462
活跃值: (53)
能力值: ( LV9,RANK:460 )
在线值:
发帖
回帖
粉丝
14
IRCBot用得比较多,不过一个简单的IDC脚本就可以全部修复了。
2009-9-7 14:05
0
雪    币: 0
活跃值: (954)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
15
thank's You!
2009-9-9 17:31
0
游客
登录 | 注册 方可回帖
返回
//