RE4B Challenge 5

2017-10-20

Challenge

What does this code do?

Optimizing GCC 4.8.4 (x64):

f:
    cmp rcx, rsi
    ja  .L10
    sub rsi, rcx
    add rsi, 1
    mov r11, rsi
    je  .L10
    test    rcx, rcx
    jne .L16
    mov rax, rdi
    ret
.L10:
    xor eax, eax
    ret
.L16:
    push    rbx
    xor r10d, r10d
    mov r9d, 1
.L4:
    lea rax, [rdi+r10]
    xor esi, esi
    xor r8d, r8d
.L8:
    movzx   ebx, BYTE PTR [rdx+rsi]
    cmp BYTE PTR [rax+rsi], bl
    cmovne  r8d, r9d
    add rsi, 1
    cmp rsi, rcx
    jne .L8
    test    r8d, r8d
    je  .L12
    add r10, 1
    cmp r10, r11
    jne .L4
    xor eax, eax
.L12:
    pop rbx

Reslove

  • xor x, x -> x = 0
  • movzx: move with zero extend.
  • cmovne: move if Not Equal to Zero.

参数:

  • arg1: int, len(a2)
  • arg2: char *
  • arg3: char *
  • arg4: int, len(a3)

等价于strstr,即寻找a2中的子串a3。

成功返回指向a2的指针,查找失败返回NULL(0);

char *f(int len_str1, char *str1, char *str2, int len_str2){
    if(len_str2 >= len_str1){
        return NULL;
    }

    int sub = len_str1 - len_str2 + 1;
    
    for(int i = 0; i < sub; ++i){
        int flag = 0;

        for(int k = 0; k < len_str2; ++k){
            if(str2[k] != str1[k + i]){
                flag = 1;
            }
        }
        
        if(flag == 0){
            return (str2 + i);
        }
    }

    return NULL;
}

分析思路

  • mov x, [y]可以判断出y是指针类型。
  • 典型的循环操作:先设置i为0,并根据i的cmp值判断跳转。
  • 有数组x就很可能有len(x)。再配合循环的计数就可以猜测出a1和a4的类型。
  • 设置一个flag,并根据flag判断是否跳转很经典。
  • 循环和逐次比较,每次只比较一个字节,很显然是字符串。