风骚的strlen

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

.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自己写的源码:

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的算法,或者已经有人写过这段代码。因为是本人自己逆向得到。斗胆贴上原创标签。

你可能感兴趣的:(源码,strlen,逆向)