搜索API函数地址

编写shellcode时,一般需使用一些API函数,例如CreateProcess(),socket()等,这些函数的入口地址位于系统的动态链接库中,由于不同操作系统的动态链接库的加载地址不同,shellcode中需增加API函数自搜索功能。

shellcode

shellcode是一段用于利用软件漏洞而执行的代码,shellcode为16进制的机器码,因为经常让攻击者获得shell而得名。shellcode常常使用机器语言编写。 可在暂存器eip溢出后,塞入一段可让CPU执行的shellcode机器码,让电脑可以执行攻击者的任意指令。

获取步骤

  1. 定位kernel32.dll地址1) 通过段选择字FS在内存中找到当前的线程控制模块TEB
    2) 线程控制块中偏移位置为0x30的地方存放着指向进程控制块PEB的指针3) 进程控制块中偏移地址0x0c的地址存放着指向PEB_LDA_DATA结构体的指针,其中存放着已经被装载的动态链接库信息。4) PEB_LDA_DATA结构体偏移地址为0x1c的地方存放着指向模块初始化链表的头指针InInitializationOrderModulelist。5) 模块初始化链表InInitializationOrderModulelist中按顺序存放着PE装入运行时初始化模块信息,第一个链表节点是ntdll.dll,第二个链表节点就是kernel32.dll。6) 找到属于kernel32.dll的节点后,在此基础上再便宜0x08就是kernel32.dll在内存中的价值基地址。
  2. 定位LoadLibrary()及GetProcAddress()地址
    1) 从kernel32.dll的加载基地址开始偏移0x3c的地方就是其PE头2) PE头偏移0x78的地方存放着指向函数导出表的指针。3) 按以下方式在导出表中算出所需函数的入口地址(1)导出表偏移0x1c处的指针指向存储导出函数偏移地址(RVA)的列表(2)导出表偏移0x20处的指针指向存储导出函数函数名的列表(3)函数的RVA地址和名称按顺序放在RVA列表及函数名列表中,根据函数名在函数名称列表中搜索函数序号,再根据函数序号在RVA列表中搜索函数对应的RVA
    (4)函数对应的RVA加上动态链接库的加载地址得到该函数的虚拟地址。

汇编代码

.386

.model flat,stdcall

option casemap:none

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\msvcrt.lib
includelib \masm32\lib\masm32.lib

include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
include \masm32\include\windows.inc
include \masm32\include\msvcrt.inc
include \masm32\include\masm32.inc
include \masm32\macros\macros.asm
.data
mesg1 db 'kernel32.dll地址: %x ',0ah , 0
mesg2 db 'LoadLibrary()地址: %x ',0ah , 0
mesg3 db 'GetProcAddress()地址: %x',0ah , 0
mesg4 db "GetProcAddress",0
mesg6 db "LoadLibraryA",0
mesg7 db "test:%x",0
add_b dd ?
.code
start:
assume fs:nothing
MOV EBX,FS:[30H]
MOV EBX,[EBX+0CH]
MOV EBX,[EBX+14H]
MOV EBX,[EBX]
MOV EBX,[EBX]
MOV EBP,[EBX+10H]
invoke crt_printf, addr mesg1,EBP ;kernel32.dll地址
MOV EAX,[EBP+3CH]
MOV ECX,[EBP+EAX+78H]
ADD ECX,EBP
MOV add_b,ECX
MOV EBX,[ECX+20H]
ADD EBX,EBP ;导出函数名列表指基地址
;invoke crt_printf, addr mesg7,EBX

XOR EDI,EDI ;清零EDI
first: ;GetProcAddress
INC EDI
MOV ESI,[EBX+EDI*4]
ADD ESI,EBP ;esi = 函数名称所在地址
invoke lstrcmp, addr mesg4, ESI
.if EAX==0
MOV EBX,dword ptr[add_b]
MOV EBX,[EBX+24H]
ADD EBX,EBP ;地址表的基地址(rva中的序号表)
MOVZX EBX,WORD PTR[EBX+2*EDI]
MOV EAX,EBX
MOV EBX,dword ptr[add_b] ;实际序号
MOV EBX,[EBX+1CH]
ADD EBX,EBP
MOV EBX,[EBX+4*EAX]
ADD EBX,EBP ;实际地址
invoke crt_printf, addr mesg3, EBX
.else
JMP first
.endif
MOV ECX,add_b
MOV EBX,[ECX+20H]
ADD EBX,EBP ;导出函数名列表指基地址
;invoke crt_printf, addr mesg7, EBX

XOR EDI,EDI
second: ;LoadLibrary
INC EDI
MOV ESI,[EBX+EDI*4]
ADD ESI,EBP ;esi = 函数名称所在地址
invoke lstrcmp, addr mesg6, ESI
.if eax==0
MOV EBX,dword ptr[add_b]
MOV EBX,[EBX+24H]
ADD EBX,EBP ;地址表的基地址(rva中的序号表)
MOVZX EBX,WORD PTR[EBX+2*EDI]
MOV EAX,EBX
MOV EBX,dword ptr[add_b] ;实际序号
MOV EBX,[EBX+1CH]
ADD EBX,EBP
MOV EBX,[EBX+4*EAX]
ADD EBX,EBP ;实际地址
invoke crt_printf, addr mesg2, EBX
ret
.else
JMP second
.endif

ret
end start