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