WindowsAPI函数地址的获取.docx

上传人:b****6 文档编号:5364180 上传时间:2022-12-15 格式:DOCX 页数:12 大小:19.20KB
下载 相关 举报
WindowsAPI函数地址的获取.docx_第1页
第1页 / 共12页
WindowsAPI函数地址的获取.docx_第2页
第2页 / 共12页
WindowsAPI函数地址的获取.docx_第3页
第3页 / 共12页
WindowsAPI函数地址的获取.docx_第4页
第4页 / 共12页
WindowsAPI函数地址的获取.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

WindowsAPI函数地址的获取.docx

《WindowsAPI函数地址的获取.docx》由会员分享,可在线阅读,更多相关《WindowsAPI函数地址的获取.docx(12页珍藏版)》请在冰豆网上搜索。

WindowsAPI函数地址的获取.docx

WindowsAPI函数地址的获取

API函数地址的获取

byHume/

前言:

病毒没有什么恐怖的,也并非象想像中的复杂,病毒就象是双刃剑,歹意利用就会带来恶果,我本人

关于此类行为深恶痛绝!

咱们研究不是为了破坏而是为了知己知彼,另外病毒中确实也有很多精湛的

技术值得咱们学习,这才是咱们的目的所在,我绝没有指令人犯法的用意。

一点理论:

这是一个老题目了,若是咱们不用任何引入库,可否在程序中挪用api函数?

固然能够!

方式有很多,你

可能早就明白了,若是你已经了解了,就此打住,这是为还不了解这一技术而写.

另外这也是病毒必用的技术之一,若是你对病毒技术感爱好,接着看下去.

那个地址假设你了解PE的大体结构,若是还不懂,找点资料来看看,处处都是呦.

 

在几乎每一个病毒的开头都用下面的语句:

 

calldelta

delta:

popebp

subebp,offsetdelta

movdwordptr[ebp+offsetappBase],ebp

让咱们考虑一下程序的执行情形,若是下面的代码由编译器自动编译连接,那么程序执行的基址一

般是400000h,若是是在Nt下执行,那么基址可能不同,比如从100000h开始,不用担忧,操作系统的Loader

会自动为你重定位.可是那个地址停下来让咱们看一下,若是你想要把这段代码附加到其他程序的后面并想

让其正确执行的话,就不是那么简单了,因为你的代码可能要从555588h处开始执行,而在没有取得宿主

程序许可的情形下期望操作系统自动为你修正偏移错误是不可能的,既然有超级的目的,就得费点力气

自己弄定重定位.而上面的代码确实是第一取得eip指针,也是delta在程序执行时的实际偏移,然后减掉

代码头到delta的偏移从而取得你的代码的真正基址,后面关于偏移的操作都应以那个真正的偏移为准.

这确实是你上面看到的.若是不明白,就认真想一下,nothingdifficult!

下面的例子演示了这一点,并

没有全数重定位,因为这只是技术演示.

此刻回到本文的正式内容,要想取得api的地址,得第一取得诸如,的基址,

然后再找到真正的函数地址.如何取得基址和函数地址呢呢?

有几种方式

1)搜寻宿主的引入表取得GetModuleHandleA函数和GetProcAddress的地址,然后通过他返回系统

dll的基址.因为很多程序都要利用这两个函数,因此在某些情形下是可行的,若是宿主没有利用

GetProcAddress,那你就不能不搜寻Export表了.

2)直接取得的基址,然后再搜寻Export表取得GetProcAddress和LoadLibraryA的地

址,然后咱们就能够取得任何想挪用的函数地址.

3)硬编码挪用函数,比如在9X下GetModuleHandleA的地址一样是BFF7****.

第一种和第三种方式存在兼容性的问题,假设宿主没有挪用GetModuleHandleA,那么你就不能取得基

址,别的就更别想了...硬编码问题更大,操作系统不同那么不能运行了,比如9X下可能在有些运算机上正常,

但确信不能在Nt/2K下运行...

第二种方式兼容性比较好,因此作以介绍.

一点背景:

在PELoader装入咱们的程序启动后堆栈顶的地址是是程序的返回地址,确信在Kernel中!

因此咱们能够取得那个地址,然后向低地址缩减验证一直到找到模块的起始地址,验证条件为PE头不能

大于4096bytes,PEheader的ImageBase值应该和当前指针相等,嘿嘿,简单吧,而且兼容性还不错.

要取得Api的地址第一要取得GetModuleHandle,LoadLibraryA,GetProcAddress的地址,这是通

点注释,没有优化代码,是为了便于明白得.

好,这一部份终止了!

代码举例:

这是一个例子,没有效任何预引入函数,加了一条invokeInitCommonControls是为了在2K下也能正常

运行,不然不能在2K下不加载!

程序取得MessageBoxA的地址然后显示一个消息框,目的在于演示,重要部份加了注释,专门好明白.

注意连接时加入/section:

.text,RWE选项。

.586

.modelflat,stdcall

optioncasemap:

none;casesensitive

includec:

\hd\

includec:

\hd\

;;--------------

GetApiAproto:

DWORD,:

DWORD

;;--------------

.CODE

appBasedd?

k32Basedd?

lpApiAddrslabelnear

ddoffsetsGetModuleHandle

ddoffsetsGetProcAddress

ddoffsetsExitProcess

ddoffsetsLoadLibrary

dd0

sGetModuleHandledb"GetModuleHandleA",0

sGetProcAddressdb"GetProcAddress",0

sExitProcessdb"ExitProcess",0

sLoadLibrarydb"LoadLibraryA",0

sMessageBoxAdb"MessageBoxA",0

 

aGetModuleHandledd0

aGetProcAddressdd0

aExitProcessdd0

aLoadLibrarydd0

aMessageBoxAdd0

u32db"",0

k32db"",0

sztitdb"ByHume,2002",0

szMsg0db"Hey,HopeUenjoyit!

",0

;;-----------------------------------------

__Start:

invokeInitCommonControls

calldelta

delta:

popebp;取得delta地址

subebp,offsetdelta;因为在其他程序中基址可能不是默许的因此需要重定位

movdwordptr[ebp+offsetappBase],ebp;呵呵认真想一想

movecx,[esp];返回地址

xoredx,edx

getK32Base:

dececx;逐字节比较验证

movdx,wordptr[ecx+];确实是ecx+3ch

testdx,0f000h;DosHeader+stub不可能太大,超过4096byte

jnzgetK32Base;加速查验

cmpecx,dwordptr[ecx+edx+jnzgetK32Base;看Image_Base值是不是等于ecx即模块起始值,

mov[ebp+offsetk32Base],ecx;若是是,就以为找到kernel32的Base值

leaedi,[ebp+offsetaGetModuleHandle]

leaesi,[ebp+offsetlpApiAddrs]

lop_get:

lodsd

cmpeax,0

jzEnd_Get

pusheax

pushdwordptr[ebp+offsetk32Base]

callGetApiA;获取API地址

stosd

jmplop_get

End_Get:

pushoffsetu32

calldwordptr[ebp+offsetaLoadLibrary];在程序空间加载

leaEDX,[EBP+OFFSETsMessageBoxA]

pushedx

pusheax

moveax,dwordptr[ebp+aGetProcAddress];用GetProcAddress取得MessageBoxA的地址

calleax;挪用GetProcAddress

push40h+1000h;style

pushoffsetsztit;title

pushoffsetszMsg0;消息内容

push0

calleax;一个消息框产生了...嘿嘿

;有理由为此快乐吧,因为咱们没有预先引入

@@:

;这些函数

push0

call[ebp+aExitProcess]

;-----------------------------------------

K32_api_retrieveprocBase:

DWORD,sApi:

DWORD

pushedx;保留edx

xoreax,eax;现在esi=sApi

Next_Api:

;edi=AddressOfNames

movesi,sApi

xoredx,edx

decedx

Match_Api_name:

movbl,byteptr[esi]

incesi

cmpbl,0

jzfoundit

incedx

pusheax

moveax,[edi+eax*4];AddressOfNames的指针,递增

addeax,Base;注意是RVA,必然要加Base值

cmpbl,byteptr[eax+edx];逐字符比较

popeax

jzMatch_Api_name;继续搜寻

inceax;不匹配,下一个api

loopNext_Api

jmpno_exist;假设全数搜完,即未存在

foundit:

popedx;edx=AddressOfNameOrdinals

shleax,1;*2取得AddressOfNameOrdinals的指针

movzxeax,wordptr[edx+eax];eax返回指向AddressOfFunctions的指针

ret

no_exist:

popedx

xoreax,eax

ret

K32_api_retrieveendp

;-----------------------------------------

GetApiAprocBase:

DWORD,sApi:

DWORD

localADDRofFun:

DWORD

pushad

movedi,Base

addedi,

movedi,[edi];此刻edi=offPE_HEADER

addedi,Base;取得IMAGE_NT_HEADERS的偏移

movebx,edi

movedi,[edi+

addedi,Base;取得edi=IMAGE_EXPORT_DIRECTORY入口

moveax,[edi+1ch];AddressOfFunctions的地址

addeax,Base

movADDRofFun,eax

;ecx=NumberOfNames

movecx,[edi+18h]

movedx,[edi+24h]

addedx,Base;edx=AddressOfNameOrdinals

movedi,[edi+20h]

addedi,Base;edi=AddressOfNames

invokeK32_api_retrieve,Base,sApi

movebx,ADDRofFun

shleax,2;要*4才取得偏移

addeax,ebx

moveax,[eax]

addeax,Base;加上Base!

mov[esp+7*4],eax;eax返回api地址

popad

ret

GetApiAendp

;-----------------------------------------

END__Start

;------------------------------------------Endall

 

API函数地址的获取

(2)

byHume/

一点理论

API地址的获取方式很多,在API函数地址的获取

(1)中介绍的方式事实上是有专门大缺点的,要求

病毒定位的代码必需在WindowsPELoader加载程序后程序未改变esp的值之前执行,也确实是说

若是程序进行了堆栈操作那么咱们无法保证[esp]中的地址还位于Kernel32中了,因此若是为了

知足多态,EPO等对Vir代码入口的不同要求,必需寻觅其他良方。

 

事实上,若是你了解Windows的SEH机制,就会专门快找到一种简单的方式。

那确实是遍历SEH链,

在链中查找prev成员等于0xFFFFFFFF的EXCEPTION_REGISTER结构(具体参见杂志的SEH介绍),

该结构中handler值是所谓的系统异样处置例程,他老是位于中!

依照这一特性,

就能够够查找在内存中的基地址了。

 

利用遍历SEH链表取得API的步骤如下:

 

a)遍历SEH链,找到prev等于0xFFFFFFFF的EXCEPTION_REGISTER结构,获取handler值;

b)用类似方式1的方式查找的基地址;

c)搜索的IAT,获取GetProcAddress的地址;

d)以GetProceAddress获取其他任何Win32API函数地址。

 

soeasy。

 

代码实例

以下是该思路的实现的例子,敬请欣赏:

;walkingthroughthesehframetogetkernel32addr

;searchtogetGetProcAddressaddr

;thenusebaseofkernel32andGetProcAddressto

;getallneededAPIs

 

 

include'%fasinc%/'

include'%fasinc%/'

 

 

.data

bufrb256

fmtdb"Kernel32baseis:

%X",0

zTitdb"ByHume2K2+",0

hModulek32dd0

.codew

api_List:

 

 

api_ends:

StArT:

xoresi,esi

lodsdword[fs:

esi]

@@:

inceax

je@F

deceax

xchgesi,eax

LODSD;nextseh_frame

jmpnear@B

@@:

LODSD;kernel32func...

;compareifPE_hdr

xchgesi,eax

find_pe_header:

decesi

xorsi,si;kernel32is64kbalign

moveax,[esi]

addax,-'MZ';antiheuristic

jnefind_pe_header

movedi,[esi+];.e_lfanew

moveax,[esi+edi]

addeax,-'PE';antiheuristic

jnefind_pe_header

;mov[hModulek32],esi

pushesi

;esi=VA

;edi=RVA

movebp,esi

movedi,[ebp+edi+]

pushediesi

 

moveax,[ebp+edi+]

movedx,[ebp+edi+]

call@F

db"GetProcAddress",0

@@:

popedi

movecx,15

subeax,4

next_:

addeax,4

addedi,ecx

subedi,15

movesi,[ebp+eax]

addesi,ebp

movecx,15

repzcmpsb

jnznext_

 

popesiedi

 

subeax,[ebp+edi+]

shreax,1

addedx,ebp

movzxeax,word[edx+eax]

addesi,[ebp+edi+]

addebp,[esi+eax*4];ebp=;useGetProcAddressandhModuletogetotherfunc

popesi;esi=kernel32Base

;int3

 

 

invokeExitProcess,0

 

.endStArT

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1