风骚的Strlen

前天逆向题目的时候,od不知道怎么抽了,竟然没有把strlen函数给标注出来。结果我害得我把strlen的代码给反编译了一遍。看完过后,脑洞大开。
这是汇编的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
.text:00401390 ; =============== S U B R O U T I N E =======================================
.text:00401390
.text:00401390 ; Attributes: library function
.text:00401390
.text:00401390 ; size_t __cdecl strlen(const char *str)
.text:00401390 _strlen proc near ; CODE XREF: _main+7Cp
.text:00401390 ; sub_401820+456p ...
.text:00401390
.text:00401390 str = dword ptr 4
.text:00401390
.text:00401390 mov ecx, [esp+str]
.text:00401394 test ecx, 3
.text:0040139A jz short main_loop
.text:0040139C
.text:0040139C str_misaligned: ; CODE XREF: _strlen+19j
.text:0040139C mov al, [ecx]
.text:0040139E inc ecx
.text:0040139F test al, al
.text:004013A1 jz short loc_4013E3
.text:004013A3 test ecx, 3
.text:004013A9 jnz short str_misaligned
.text:004013AB add eax, 0
.text:004013B0
.text:004013B0 main_loop: ; CODE XREF: _strlen+Aj
.text:004013B0 ; _strlen+36j ...
.text:004013B0 mov eax, [ecx]
.text:004013B2 mov edx, 7EFEFEFFh
.text:004013B7 add edx, eax
.text:004013B9 xor eax, 0FFFFFFFFh
.text:004013BC xor eax, edx
.text:004013BE add ecx, 4
.text:004013C1 test eax, 81010100h
.text:004013C6 jz short main_loop
.text:004013C8 mov eax, [ecx-4]
.text:004013CB test al, al
.text:004013CD jz short loc_401401
.text:004013CF test ah, ah
.text:004013D1 jz short loc_4013F7
.text:004013D3 test eax, 0FF0000h
.text:004013D8 jz short loc_4013ED
.text:004013DA test eax, 0FF000000h
.text:004013DF jz short loc_4013E3
.text:004013E1 jmp short main_loop
.text:004013E3 ; ---------------------------------------------------------------------------
.text:004013E3
.text:004013E3 loc_4013E3: ; CODE XREF: _strlen+11j
.text:004013E3 ; _strlen+4Fj
.text:004013E3 lea eax, [ecx-1]
.text:004013E6 mov ecx, [esp+str]
.text:004013EA sub eax, ecx
.text:004013EC retn
.text:004013ED ; ---------------------------------------------------------------------------
.text:004013ED
.text:004013ED loc_4013ED: ; CODE XREF: _strlen+48j
.text:004013ED lea eax, [ecx-2]
.text:004013F0 mov ecx, [esp+str]
.text:004013F4 sub eax, ecx
.text:004013F6 retn
.text:004013F7 ; ---------------------------------------------------------------------------
.text:004013F7
.text:004013F7 loc_4013F7: ; CODE XREF: _strlen+41j
.text:004013F7 lea eax, [ecx-3]
.text:004013FA mov ecx, [esp+str]
.text:004013FE sub eax, ecx
.text:00401400 retn
.text:00401401 ; ---------------------------------------------------------------------------
.text:00401401
.text:00401401 loc_401401: ; CODE XREF: _strlen+3Dj
.text:00401401 lea eax, [ecx-4]
.text:00401404 mov ecx, [esp+str]
.text:00401408 sub eax, ecx
.text:0040140A retn
.text:0040140A _strlen endp
.text:0040140A
.text:0040140A ; ---------------------------------------------------------------------------

然后是我借助IDA的F5自己写的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
size_t __cdecl _strlen(const char *str)
{
const char *str1;
char begin;
int temp;
int length;

str1 = str;
if((unsigned int)str & 3 )
{
do
{
begin = *str1++;
if ( !begin )
return str1 - 1 - str;
}
while ( (unsigned int)str1 & 3 );
}

while ( 1 )
{
do
{
temp = (*(unsignedint *)str1 + 0x7EFEFEFF) ^ (~*(unsignedint *)str1);
str1 += 4;
}
while ( !(temp & 0x81010100) );
length = *((int *)str1 - 1);
if ( !(unsigned char)length )
break;
if ( !(unsigned char)(length>>8) )
return str1 - 3 - str;
if ( !(length & 0xFF0000) )
return str1 - 2 - str;
if ( !(length & 0xFF000000) )
return str1 - 1 - str;
}
return str1 - 4 - str;
}

风骚的代码,自己看看就好。
新手一枚,并不知道网上是否已经有了strlen的算法,或者已经有人写过这段代码。因为是本人自己逆向得到。斗胆贴上原创标签。