Open your Linux Terminal and compile the source code. Just ignore the error message.
darklinux@darklinuxpc:~$ gcc pass.c -o pass
pass.c: In function ‘main’:
pass.c:10:3: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
gets(password);
^~~~
fgets
/tmp/ccN6YiCB.o: In function main': pass.c:(.text+0x35): warning: the
gets' function is dangerous and should not be used.
darklinux@darklinuxpc:~$ ls -l pass
-rwxrwxr-x 1 darklinux darklinux 8512 Oct 20 19:36 pass
darklinux@darklinuxpc:~$
Run the program and input any password.
darklinux@darklinuxpc:~$ ./pass Enter your password: 123 Wrong password! darklinux@darklinuxpc:~$
As you can see, we the program display ‘Wrong password’ because when program compare with your input and it’s not the same the correct password key which is “passwordkey”.
Now, let’s modify it.
We will use gdb to find the assembly code for compare the key then change it with vim.
Below are the assembly line codes for ‘pass’ program. Since we have the source code and we want to observe how it work, you don’t have to understand each line, just focus on ‘input’ and ‘compare the input’.
darklinux@darklinuxpc:~$ gdb --silent pass Reading symbols from pass…(no debugging symbols found)…done. (gdb) set disassembly-flavor intel (gdb) disassemble main Dump of assembler code for function main: 0x000000000000078a <+0>: push rbp 0x000000000000078b <+1>: mov rbp,rsp 0x000000000000078e <+4>: sub rsp,0x20 0x0000000000000792 <+8>: mov rax,QWORD PTR fs:0x28 0x000000000000079b <+17>: mov QWORD PTR [rbp-0x8],rax 0x000000000000079f <+21>: xor eax,eax 0x00000000000007a1 <+23>: lea rdi,[rip+0xfc] # 0x8a4 0x00000000000007a8 <+30>: mov eax,0x0 0x00000000000007ad <+35>: call 0x640 0x00000000000007b2 <+40>: lea rax,[rbp-0x20] 0x00000000000007b6 <+44>: mov rdi,rax 0x00000000000007b9 <+47>: mov eax,0x0 0x00000000000007be <+52>: call 0x660 0x00000000000007c3 <+57>: lea rax,[rbp-0x20] 0x00000000000007c7 <+61>: lea rsi,[rip+0xec] # 0x8ba 0x00000000000007ce <+68>: mov rdi,rax 0x00000000000007d1 <+71>: call 0x650 0x00000000000007d6 <+76>: test eax,eax 0x00000000000007d8 <+78>: je 0x7e8 0x00000000000007da <+80>: lea rdi,[rip+0xe5] # 0x8c6 0x00000000000007e1 <+87>: call 0x620 0x00000000000007e6 <+92>: jmp 0x7f2 0x00000000000007e8 <+94>: mov eax,0x0 0x00000000000007ed <+99>: call 0x80d 0x00000000000007f2 <+104>: mov eax,0x0 0x00000000000007f7 <+109>: mov rdx,QWORD PTR [rbp-0x8] 0x00000000000007fb <+113>: xor rdx,QWORD PTR fs:0x28 0x0000000000000804 <+122>: je 0x80b 0x0000000000000806 <+124>: call 0x630 <__stack_chk_fail@plt> 0x000000000000080b <+129>: leave 0x000000000000080c <+130>: ret End of assembler dump. (gdb) x/s 0x8a4 0x8a4: "Enter your password: " (gdb) x/s 0x8c6 0x8c6: "\nWrong password!" (gdb) x/4x 0x00000000000007d8 0x7d8 : 0x74 0x0e 0x48 0x8d (gdb) quit darklinux@darklinuxpc:~$
Note:
x/s 0x8a4 ← display address 0x8a4
x/s 0x8c6 ← display address 0x8c6
x/4x 0x00000000000007d8 ← display 4 hexadecimal value of address 0x00000000000007d8
We can focus on the 2 line codes below.
0x00000000000007d6 <+76>: test eax,eax
0x00000000000007d8 <+78>: je 0x7e8 <main+94>
The first line is to compare the correct key with the input.
The second line, if the input is equal with the key, jump to codes that display ‘Access Granted’.
If not equal, then process display ‘Wrong password’.
(gdb) x/4x 0x00000000000007d8
0x7d8 <main+78>: 0x74 0x0e 0x48 0x8d
0x74 → is the code for ‘JE (Jump short if equal)’
0x0e → is the offset address
0x00000000000007d8 <+78>: je 0x7e8 <main+94>
0x00000000000007da <+80>: lea rdi,[rip+0xe5] # 0x8c6
0x00000000000007e1 <+87>: call 0x620 <puts@plt>
0x00000000000007e6 <+92>: jmp 0x7f2 <main+104>
0x00000000000007e8 <+94>: mov eax,0x0
0x00000000000007ed <+99>: call 0x80d <granted>
How to count the jump address of “je 0x7e8”?
Taking the next address, 7da then add the offset value.
→ 7da + 0e = 7e8
You can get the reference from:
Intel® 64 and IA-32 Architectures
Software Developer’s Manual
Volume 2A:
Instruction Set Reference, A-L
Now we know the program use JE for jump if equal.
If we change it to JNE (jump if not equal) then any input that not macth with key password will always process as equal. It mean, any input key that don’t match will always get ‘Access Granted’.
Run vim.
$ vim pass
Content of pass program.
Dump pass program to hexadecimal code.
:%!xxd <press Enter>
Pass program in hexadecimal code
Find hexadecimal value ‘740e’.
/740e <press enter>As you can see, vim hilite the founded value.
Press ‘Enter’ and ‘i’ (to change vim to insert mode)
Change the value 74 (JE) to 75 (JNE).
Reverse the hexadecimal code to file
:%!xxd -r
Save the file and quit.
:wq
Test the program.
darklinux@darklinuxpc:~$ ./pass
Enter your password: 123
Access granted!
darklinux@darklinuxpc:~$ ./pass
Enter your password: asdfadsf
Access granted!
darklinux@darklinuxpc:~$
As you can see, any input that I key in, it always Granted.
If you want to go deeper about reverse engineering, below some books that I recommend to read:
-Mastering Reverse Engineering, Reginald Wong, Copyright © 2018 Packt Publishing
-Reverse Engineering for Beginners, Dennis Yurichev, ©2013-2015, Dennis Yurichev
-Reverse Engineering-Recent advances and applications, Alexandru C. Telea, Copyright © 2012 InTech
-Reversing: Secrets of Reverse Engineering, Eldad Eilam, Copyright © 2005 by Wiley Publishing, Inc.
Leave a comment