介绍:本文不静态引入任何库文件 动态获取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直播授课