现在的位置: 首页 > 综合 > 正文

strlen函数的反汇编

2014年03月27日 ⁄ 综合 ⁄ 共 2571字 ⁄ 字号 评论关闭

本来我自己计算的时候写了一大堆,不过还是挑重点的讲吧:

这是strlen的反汇编代码

004010F0 >/$  8B4C24 04     mov ecx,dword ptr ss:[esp+0x4]           ;  ecx=字符串地址
004010F4  |.  F7C1 03000000 test ecx,0x3
004010FA  |.  74 14         je short Test_CPP.00401110
004010FC  |>  8A01          /mov al,byte ptr ds:[ecx]
004010FE  |.  41            |inc ecx
004010FF  |.  84C0          |test al,al
00401101  |.  74 40         |je short Test_CPP.00401143
00401103  |.  F7C1 03000000 |test ecx,0x3
00401109  |.^ 75 F1         \jnz short Test_CPP.004010FC
0040110B  |.  05 00000000   add eax,0x0
00401110  |>  8B01          /mov eax,dword ptr ds:[ecx]
00401112  |.  BA FFFEFE7E   |mov edx,0x7EFEFEFF
00401117  |.  03D0          |add edx,eax
00401119  |.  83F0 FF       |xor eax,0xFFFFFFFF
0040111C  |.  33C2          |xor eax,edx
0040111E  |.  83C1 04       |add ecx,0x4
00401121  |.  A9 00010181   |test eax,0x81010100
00401126  |.^ 74 E8         |je short Test_CPP.00401110
00401128  |.  8B41 FC       |mov eax,dword ptr ds:[ecx-0x4]
0040112B  |.  84C0          |test al,al
0040112D  |.  74 32         |je short Test_CPP.00401161
0040112F  |.  84E4          |test ah,ah
00401131  |.  74 24         |je short Test_CPP.00401157
00401133  |.  A9 0000FF00   |test eax,0xFF0000
00401138  |.  74 13         |je short Test_CPP.0040114D
0040113A  |.  A9 000000FF   |test eax,0xFF000000
0040113F  |.  74 02         |je short Test_CPP.00401143
00401141  |.^ EB CD         \jmp short Test_CPP.00401110
00401143  |>  8D41 FF       lea eax,dword ptr ds:[ecx-0x1]
00401146  |.  8B4C24 04     mov ecx,dword ptr ss:[esp+0x4]
0040114A  |.  2BC1          sub eax,ecx
0040114C  |.  C3            retn
0040114D  |>  8D41 FE       lea eax,dword ptr ds:[ecx-0x2]
00401150  |.  8B4C24 04     mov ecx,dword ptr ss:[esp+0x4]
00401154  |.  2BC1          sub eax,ecx
00401156  |.  C3            retn
00401157  |>  8D41 FD       lea eax,dword ptr ds:[ecx-0x3]
0040115A  |.  8B4C24 04     mov ecx,dword ptr ss:[esp+0x4]
0040115E  |.  2BC1          sub eax,ecx
00401160  |.  C3            retn
00401161  |>  8D41 FC       lea eax,dword ptr ds:[ecx-0x4]
00401164  |.  8B4C24 04     mov ecx,dword ptr ss:[esp+0x4]
00401168  |.  2BC1          sub eax,ecx
0040116A  \.  C3            retn
0040116B      CC            int3
0040116C      CC            int3
0040116D      CC            int3
0040116E      CC            int3
0040116F      CC            int3
00401170 >/$  75 01         jnz short Test_CPP.00401173
00401172  |.  C3            retn

看起来有点长得不可理喻啊,不过这种方法对于长字符串来说是要比以下这种方法快四倍的:

repne scasb
not ecx
dec dec

下面来分析下这个函数:

004010F0 >/$  8B4C24 04     mov ecx,dword ptr ss:[esp+0x4]           ;  ecx=字符串地址
004010F4  |.  F7C1 03000000 test ecx,0x3
004010FA  |.  74 14         je short Test_CPP.00401110
004010FC  |>  8A01          /mov al,byte ptr ds:[ecx]
004010FE  |.  41            |inc ecx
004010FF  |.  84C0          |test al,al
00401101  |.  74 40         |je short Test_CPP.00401143
00401103  |.  F7C1 03000000 |test ecx,0x3
00401109  |.^ 75 F1         \jnz short Test_CPP.004010FC

这段代码主要是用来测试字符串地址是否为0,4,8,C结尾的,因为:

0011(0x3)
AND
1100(0xC)
1000(0x8)
0100(0x4)
0000(0x0)
EQUAL
0x0

但是如果字符串长度小于4的话这段代码也能直接计算这个字符串的长度


后面的部分代码可以如下表示:(其中four(str)为递增的四个字符,每一次循环都取下个四字符)

eax=【four(str) xor 0xFFFFFFFF】xor【four(str) + 0x7EFEFEFF】

if(and(eax,81010100)!=0) then ok,计算长度


你会发现0x7EFEFEFF的二进制串很有规律:

01111110111111101111111011111111(隔一段就出现一次0,不妨将出现0的地方称为零点吧)

而0x7EFEFEFF+0000006B(包含0x0),就会使得某些零点变为1,然后再进行xor 【four(str) xor 0xFFFFFFFF】也是不会改变这个事实的

这个时候and(eax,81010100)就会不等于0了,因为81010100的二进制串为:10000001000000010000000100000000(原来是零点的地方现在都是1了)

抱歉!评论已关闭.