Monday, October 7, 2024

Ask HN: Correct Logic written in C, but Compiler messed things up?

I was solving some easy Reverse engineering challenges when I came across a peculiar binary.It was a simple password checker with code that seemed correct but during compilation the compiler seemed to mess something up. Have a look.

Section of main function:

    0x00001213      lea     rax, [str.64s] ; 0x2032
    0x0000121a      mov     rdi, rax   ; const char *format
    0x0000121d      mov     eax, 0
    0x00001222      call    __isoc99_scanf ; sym.imp.__isoc99_scanf ; int scanf(const char *format)
    0x00001227      lea     rax, [var_48h]
    0x0000122b      mov     rdi, rax   ; int64_t arg1
    0x0000122e      call    checkPass  ; sym.checkPass ;  sym.checkPass(int64_t arg1)
    0x00001233      test    eax, eax
    0x00001235      je      0x124d
    0x00001237      lea     rax, [str.You_are_correct_:] ; 0x2037
    0x0000123e      mov     rdi, rax   ; const char *format
    0x00001241      mov     eax, 0
    0x00001246      call    printf     ; sym.imp.printf ; int printf(const char *format)
    0x0000124b      jmp     0x1261
    0x0000124d      lea     rax, [str.Better_luck_next_time._:] ; 0x204a
    0x00001254      mov     rdi, rax   ; const char *format
    0x00001257      mov     eax, 0
    0x0000125c      call    printf     ; sym.imp.printf ; int printf(const char *format)
    0x00001261      mov     eax, 0
    0x00001266      leave
    0x00001267      ret

checkPass function:
    0x00001149      push    rbp
    0x0000114a      mov     rbp, rsp
    0x0000114d      mov     qword [input], rdi ; arg1
    0x00001151      mov     rax, qword [input]
    0x00001155      movzx   eax, byte [rax]
    0x00001158      cmp     al, 0x73
    0x0000115a      jne     0x11cc
    0x0000115c      mov     rax, qword [input]
    0x00001160      add     rax, 1
    0x00001164      movzx   eax, byte [rax]
    0x00001167      cmp     al, 0x75
    0x00001169      jne     0x11d3
    0x0000116b      mov     rax, qword [input]
    0x0000116f      add     rax, 2
    0x00001173      movzx   eax, byte [rax]
    0x00001176      cmp     al, 0x64
    0x00001178      jne     0x11d3
    0x0000117a      mov     rax, qword [input]
    0x0000117e      add     rax, 3
    0x00001182      movzx   eax, byte [rax]
    0x00001185      cmp     al, 0x6f
    0x00001187      jne     0x11d3
    0x00001189      mov     rax, qword [input]
    0x0000118d      add     rax, 4
    0x00001191      movzx   eax, byte [rax]
    0x00001194      cmp     al, 0x30
    0x00001196      jne     0x11d3
    0x00001198      mov     rax, qword [input]
    0x0000119c      add     rax, 5
    0x000011a0      movzx   eax, byte [rax]
    0x000011a3      cmp     al, 0x78
    0x000011a5      jne     0x11d3
    0x000011a7      mov     rax, qword [input]
    0x000011ab      add     rax, 6
    0x000011af      movzx   eax, byte [rax]
    0x000011b2      cmp     al, 0x31
    0x000011b4      jne     0x11d3
    0x000011b6      mov     rax, qword [input]
    0x000011ba      add     rax, 7
    0x000011be      movzx   eax, byte [rax]
    0x000011c1      cmp     al, 0x38
    0x000011c3      jne     0x11d3
    0x000011c5      mov     eax, 1
    0x000011ca      jmp     0x11d3
    0x000011cc      mov     eax, 0
    0x000011d1      jmp     0x11d3
    0x000011d3      pop     rbp
    0x000011d4      ret
The author did make a mistake of returning 0 if the first letter matches and 1 only if all letters match. This makes it ambiguous as to what should happen if only 2 or 3 or so letters match.

However, the way the compiler handles it (by storing bytes and the return value both in the eax register) leads to a flaw where a person can bypass the check by just entering "ss" (for example). Is this the compiler's mistake? How can we avoid such a scenario?


Comments URL: https://news.ycombinator.com/item?id=41769051

Points: 1

# Comments: 0



from Hacker News: Newest https://ift.tt/NWIGbfV

0 comments:

Post a Comment