众人好,我近来从Wb平安最先进修二进制平安,分享一下自身进修过程的成绩和心体面会。由因而初学的体例,因此对于二进制大佬来讲这很简明,因此本文紧要面向的目标主借使和我同样始终做Wb平安,又想初学二进制平安的人。本次我进修的案例是木马和病毒罕用的一个技巧:保证惟独一个病毒或许木马在系统中运转,即运转简明实例。对于病毒和木马而言,假如屡次反复运转,会补充泄漏的危险。因此要保证系统中只运转一个病毒或木马的历程。
1.1.正向编写C代码
要完结运转简明实例,一种罕见且简明的办法是经过建立系统定名互斥目标完结的,这类办法主借使哄骗CratMutx函数,经过该函数咱们也也许视察是不是曾经有一个历程运转了。那末,假如经过CratMutx函数得悉是不是曾经有一个在运转的历程了呢?
底下扼要引见下CratMutx函数,它的性能是建立或许翻开一个已定名或许未定名的互斥目标。
对于它的返回值,假如函数胜利,则返回值是新建立的互斥目标的句柄。假如函数失利,则返回值为NULL。要得到增添的差错消息,请挪用GtLastError。假如互斥锁是一个已定名的互斥锁,而且该目标在此函数挪用以前就存在,则返回值是现有目标的句柄,GtLastError返回ERROR_ALREADY_EXISTS。
简明点来讲,即是假如CratMutx函数的返回值不是NULL,而且挪用GtLastError函数后,返回值是ERROR_ALREADY_EXISTS,那末也许断定曾经存在了一个在运转的历程。用C言语代码完结以下:
运用VC++6.0结尾编译链接后生成可施行文献,双击运转,显示以下:
在不紧闭上述历程的前提下,再次双击生成的可施行文献,显示以下:
也许看出当系统中运转第二个历程的时刻,输出了AlradyRun!!!!阐述程序曾经胜利地判定出反复运转了。
1.2.逆向解析
底下咱们就对这个程序实行逆向解析,咱们须要对主函数和子函数别离实行逆向解析,此次先解析主函数。
对于进修的办法,我的成绩是在初学阶段,咱们先解析自身写的代码,解析完以后再实行印证,渐渐地就也许摆脱源码并试验解析其它未公然源码的程序过程。
在进修过程中,至极紧急的一点是:要分清主次。甚么事理呢?
进修汇编言语和逆向,咱们齐备没有须要逐条指令去留意赏玩悉数的代码,紧急的是从全体上了解程序到底做了哪些职掌。汇编言语也是一种编程言语,寻常众人也不会去一行一行地留意赏玩他人写的大批代码,除了务须要了解的紧急部份花时候留意读一读,余下的部份根基都是一带而过,唯有大概上了解程序在做甚么事就行了。逆向工程也是同样,“紧急的部份花时候留意了解”“其它部份大约懂得何如回事就好”这两条绳尺同样实用。
那末哪些是紧急的呢?在病毒木马解析中,个中一点对照紧急的是解析call函数,唯有将这个程序所挪用的函数解析知道了,那末就懂得这个病毒木马在做甚么了。与此同时要弄知道它的逻辑组织,好比甚么时刻跳转到哪施行。
接下来咱们首先对主函数实行解析。
1.2.1.主函数:
主函数的C言语代码以下图所示:
底下对其汇编代码实行解析:
_main_0procnarvar_40=bytptr-40hpushbpmovbp,spsubsp,40hpushbxpushsipushdiladi,[bp+var_40]movcx,10hmovax,0CCCCCCCChrpstosd
以上代码结尾悉数的函数入栈职掌,每个函数最先时城市有如许的职掌,这边咱们无需过火细究,如感爱好,对这段代码详细的解析可参考《C++反汇编与逆向解析技巧揭秘》p,我也将其紧要的体例贴出来了:
对于这段体例中补充引见两个指令,个中,xorax,ax直接会将ax的值配置为0,这是将寄放器配置为0最罕见的方法,cmp指令是前提指令,详细体例以下图所示:
这段体例在这边短暂唯有懂得,无需查究,等须要的时刻再去协商也不迟。
以后,到了须要认谬误解的场合了,下一条的指令是
callsub_
它的事理是挪用子函数sub_,在这边原来对应的是咱们编写的IsAlradyRun函数。
须要补充的是在函数调历时,假如有参数须要传送,须要在call指令以前,运用push先将参数从后往前入栈。这边由于无任何参数传送,因此在挪用以前,无需运用push指令将参数入栈。背面还会详细引见是何如从后往前入栈的,这边须要先记着这个学识点。
尚有一个要记着的是在函数挪用结尾后,VC中,会运用ax寄放器来保管函数的返回值。
接下来的一条指令是
tstax,ax
对于tst指令,唯有记着若ax为0,则zf标识位会配置为1,此时ax中的值是上一条指令的返回值,若对tst指令感爱好可参考以下注解:
接下来的指令是
jzshortloc_E0
jz是跳转指令,即jumpzro,即当零标识位ZF=1的时刻跳转到loc_E0这个地方施行,此时也即是上一个指令tstax,ax得到的职掌使得ZF=1,也即是ax=0,由于ax保管的是子函数的返回值,因此咱们得悉子函数的返回值为0。由咱们编写的C言语代码可知,此时对应的是IsAlradyRun函数返回效果为fals,和咱们的解析相对应。
跳转到该地方后:
loc_E0:;"NOTAlradyRun!\n"pushoffstaNotAlradyRuncall_printfaddsp,4
也许看到的call_printf指令,这将会挪用printf输出函数。由于printf须要传送参数,因此在call_printf以前,须要先施行push的职掌。咱们将鼠标放在aNotAlradyRun上也许看到对应的字符串与loc_E0:后的备注消息"NOTAlradyRun!\n"同样,以下图所示:
因此得出论断,若子函数sub_的返回值为0时,跳转到loc_E0地方,将会输出"NOTAlradyRun!\n"。与咱们编写的C言语代码相吻合。
那末,若子函数sub_的返回值为1时,会何如样呢?
此时,会走到左侧的施行框内,不会跳转到右侧。同理,这边将会输出"NOTAlradyRun!\n"字符串。
施行结尾后,左右双方的体例城市到loc_ED这个地方接续施行:
这段体例看到有callds:Slp指令,此处是挪用了Slp函数,对应的是咱们C代码中的Slp():
由于要传送参数,因此须要先将参数入栈,即push职掌,也许看到在callds:Slp指令以前,有pushA0h指令,将鼠标安顿在A0h上,右键可视察对应的十进制:
恰巧也是0,因此和咱们编写的C代码也恰巧吻合。
以后,运用pop和call__chksp等指令,结尾出栈、检讨栈均衡等函数返回做事。
今朝,对于主函数的解析曾经结尾,下篇咱们一同进一步对联函数实行详细的解析。
参考书本《Windows黑客编程技巧详解》甘迪文著--北京:国民邮电出书社,年12月。
《C++反汇编与逆向解析技巧揭秘》钱松林,赵海旭著--北京:机器产业出书社,年9月。
《歹意代码解析实战》(美)MichalSikorski/AndrwHonig著,诸葛建伟,姜辉,张光凯译--北京:电子产业出书社,年4月,原书名:PracticalMalwarAnalysis:ThHands-OnGuidtoDissctingMaliciousSoftwar。
《汇编言语》王爽著--2版,北京:清华大学出书社,年4月。
熟练举荐区
联系熟练:ARM汇编教程