原理介绍
API自搜索技术原理
masm32
链接: masm32下载链接
说明:解压至本地配置环境变量即好,另附本次实验源码一份,masm32主目录下
环境变量配置如下图所示:
编译指令:ml -c -coff 文件名(.asm文件);
链接指令:link /subsystem:console 文件名(.obj文件);
展示部分
汇编源码展示
.686
.model flat,stdcall
option casemap:none
includelib lib\kernel32.lib ;包含API函数的导入库文件
ExitProcess proto,:dword ;Windows函数声明
exit macro dwexitcode
invoke ExitProcess,dwexitcode
endm
GetStdHandle proto,:dword
WriteConsoleA proto,:dword,:dword,:dword,:dword,:dword
WriteConsole equ<WriteConsoleA>
ReadConsoleA proto,:dword,:dword,:dword,:dword,:dword
ReadConsole equ<ReadConsoleA>
STD_OUTPUT_HANDLE=-11 ;Windows常量定义
STD_INPUT_HANDLE=-10 ;Windows常量定义
GetConsoleMode proto,:dword,:dword
SetConsoleMode proto,:dword,:dword
.data
arg dword 0
msg1 byte 'kernel32.dll virtual address=0x',0
msg byte 10,0 ;字符串,10为换行
fname1 byte 'GetProcAddress',0
fname2 byte 'LoadLibraryA',0
attention byte '######################Successfully find functions!########################',10,0
outsize dword ?
inhandle dword ?
savemode dword ?
insize dword ?
inbuffer byte 255 dup(0)
.code
start:
;Get kernel32.dll base addr
assume fs:nothing
mov eax,fs:[30h] ;PEB
mov eax,[eax+0ch] ;PROCESS_MODULE_INFO
mov esi,[eax+1ch] ;InInitOrder.flink
lodsd ;eax=InInitOrder.blink
mov ebp,[eax+8] ;ebp=kernel32.dll base address
mov eax,offset msg1
call dispmsg
mov eax,ebp
call dispx
push esi
mov esi,[ebp+03Ch] ;[esi]->PE头地址
mov esi,[esi+ebp+078h]
add esi,ebp ;[esi]->导出表
push esi ;压栈保存
mov esi,[esi+020h]
add esi,ebp ;[esi]->存储导出函数函数名列表的首地址
pop edi
mov edi,[edi+01Ch]
add edi,ebp ;[edi]->存储导出函数地址列表的首地址
push eax
mov eax,offset attention
call dispmsg
mov ecx,1000
forloop:
lodsd ;mov eax,[esi], esi=esi+4
add eax,ebp ;[eax]->导出函数函数名列表一个导出函数的名称
mov ebx,[edi]
add edi,4
add ebx,ebp ;[ebx]->导出函数地址列表一个导出函数的地址
;依次对比函数名称,找fname1和fname2
push ebx ;ebx压栈保存
mov ebx,eax ;传入第一个字符串首地址
mov edx,offset fname1 ;传入第二个字符串首地址
call cmpname ;两字符串相等,则edx=1
test edx,1
jnz print ;打印输出函数名和函数地址
pop ebx
push ebx ;ebx压栈保存
mov ebx,eax ;传入第一个字符串首地址
mov edx,offset fname2 ;传入第二个字符串首地址
call cmpname ;两字符串相等,则edx=1
test edx,1
jnz print ;打印输出函数名和函数地址
pop ebx
loop forloop
;获取句柄
invoke GetStdHandle,STD_OUTPUT_HANDLE
;显示信息,提示按任意键退出
invoke WriteConsole,eax,addr msg,sizeof msg,addr outsize,0
invoke GetStdHandle,STD_INPUT_HANDLE
mov inhandle,eax
invoke GetConsoleMode,inhandle,addr savemode ;获得控制台模式
invoke SetConsoleMode,inhandle,0 ;设置为单字符输入模式
invoke ReadConsole,inhandle,addr inbuffer,1,addr insize,0 ;输入字符
invoke SetConsoleMode,inhandle,savemode ;恢复原控制台模式
;退出
exit 0
invoke ExitProcess,0
.data ;子程序DISPMSG使用的变量
_outsize dword ?
_outhandle dword ?
.code
dispmsg proc ;字符串显示子程序,入口参数:EAX=
push eax
push ebx
push ecx
push edx
push eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov _outhandle,eax ;句柄实例保存,以便后续调用
pop ebx ;弹出字符串地址送入EBX
xor ecx,ecx
;计算字符串长度
dispm1: mov al,[ebx+ecx]
test al,al ;[al] and [al],不改变寄存器内容,同时修改ZF标志位
jz dispm2
inc ecx
jmp dispm1
dispm2: invoke WriteConsole,_outhandle,ebx,ecx,addr _outsize,0
pop edx
pop ecx
pop ebx
pop eax
ret
dispmsg endp
.data ;子程序DISPX使用的变量
regd byte 8 dup(0),10,0 ;显示EAX中的16进制数,预留8个字节空间
.code
dispx proc ;16进制数显示子程序,入口参数:EAX=
push ebx
push ecx
push edx
mov ecx,8
xor ebx,ebx ;使用ebx相对寻址访问regd,故初始化ebx=0
again: rol eax,4 ;高4位循环移位进入低4位,作为子程序htoasc的入口参数
push eax ;子程序htoasc使用al返回结果,所以需要压栈保存eax
call htoasc ;调用子程序htoasc
mov regd+[ebx],al ;保存转换后的ASCII码
pop eax ;恢复保存的数据
inc ebx
loop again
mov eax,offset regd
call dispmsg ;显示
pop edx
pop ecx
pop ebx
ret
dispx endp
.data ;子程序htoasc使用的数据
ASCII byte '0123456789ABCDEF'
.code
htoasc proc ;将al的低4位表达的一位16进制数转换为ASCII码
and eax,0fh ;取al低四位
mov al,ASCII+[eax] ;换码
ret
htoasc endp
.code
cmpname proc ;比对字符串是否一致,ebx、edx接受两字符串首地址,返回edx
push eax
push ecx
xor ecx,ecx
Loopx: mov al,[ebx+ecx]
mov ah,[edx+ecx]
cmp al,ah ;比较相应两字符
jnz different ;不等则跳转结束
inc ecx ;偏移地址+1
cmp al,0 ;比对结束
jz done
jmp Loopx
done: cmp ah,0 ;判断另一字符串是否结束
jz same ;两字符串相同
jnz different ;两字符串不同
same: pop ecx
pop eax
mov edx,1
ret
different: pop ecx
pop eax
mov edx,0
ret
cmpname endp
.data
fun_name byte 'Function name:',0
fun_addr byte 'Function address',0
space byte ' ',0
new_line byte 10,0
.code
print proc ;参数变量为eax、ebx
push ebx
push eax
push eax
mov eax,offset fun_name
call dispmsg
pop eax
mov eax,eax
call dispmsg
mov eax,offset space
call dispmsg
mov eax,offset fun_addr
call dispmsg
mov eax,ebx
call dispx
pop eax
pop ebx
jmp forloop
ret
print endp
end start
运行结果展示
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210103001014465.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0ODA2MzA1,size_16,color_FFFFF