This page looks best with JavaScript enabled

Binary fun

 ·  ☕ 5 min read

Binary Fun: With basic binary file analysis

A little bit ago I decided CTFs looked like alot of fun and that I want to get involved. At least for me it was a little daunting picking where to start. Some people would start with things they are familiar with but I thought Reverse Engineering sounded cool so I went with that. I got a small binary made by a friend, intended to be similar to a basic reversing challenge, to start with.

First steps

The file is titled pwd2 and we can run a couple of quick bash commands to see if we can find any useful information. I went ahead and spun up a fresh Ubuntu VM for obvious reasons. Of course lets run it first and see what it wants.

user@ubuntu:~$./pwd2
Please supply 3 digit passcode
222
Nope

The next thing to do would be to run the file command and see if we can grab any other basic information.

user@ubuntu:~$file pwd2
ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID<br />
[sha1]=82ef1e7313ec65f084871b449de99df70ba27282, stripped

Alright so it is pretty apparent what it wants. At the time I first received this I didnt know about String Format vulns otherwise I wouldve tried seeing if I couldve gained the password value that way. Additionally I didnt think to try integer underflow or overflow, but I did try a simple buffer overflow and can say that did not work.

At least now Ive got some more ideas of things to look for. The one useful thing I did get from that file command was that debug symbols are stripped.

Despite seeing that the binary is stripped, I am still going to try gdb on it. Ive used it before with varying degrees of success and still want to become better with it.

user@ubuntu:~$ gdb ./pwd2
(gdb) r
Starting program: /home/user/ex1/pwd2 
denied.

[Inferior 1 (process 7311) exited with code 01]
(gdb)

Having seemingly hit a wall here, I put a good bit of googling to work. Most on obfuscation of C binaries and things that would try to prevent debuggers. Fortunately I found an article on Securing iOS apps that mentioned a bit about how one may prevent a debugger using dlsym. Dlsym would be dynamically opening a library and calling some sort of function to prevent our debugger. Ubuntu has a nifty tool called ltrace, or library trace, that will call the program and run it until exit. All the while recording all of the dynamic library calls.

user@ubuntu:~$ ltrace ./pwd2
__libc_start_main(0x4007ed, 1, 0x7fff898547b8, 0x400850 <unfinished ...>
dlopen(nil, 258)                                                                                         = 0x7f32fd4971c8
dlsym(0x7f32fd4971c8, "ptrace")                                                                          = 0x7f32fcd9c4f0
puts("denied.\n"denied.

So there we have it, ptrace is preventing our debugger. Which is neat new knowledge but Im going to exhaust all other low hanging fruit before I begin to look into what more I can do with that.

Lets run strings, because sometimes, it really does work.

user@ubuntu:~$ strings ./pwd2
/lib64/ld-linux-x86-64.so.2
libdl.so.2
_ITM_deregisterTMCloneTable
__gmon_start__
_Jv_RegisterClasses
_ITM_registerTMCloneTable
dlclose
dlsym
dlopen
libc.so.6
exit
__isoc99_scanf
puts
__libc_start_main
GLIBC_2.2.5
GLIBC_2.7
UH-h
UH-h
=1	 
[]A\A]A^A_
ptrace
denied.
Please supply 3 digit passcode
Nope
Win.
;*3$

It was unlikely that an int would be stored as a string but it only takes quick moment to verify.

A big part of learning reverse engineering has been attemping to become comfortable with assembly. I did have to learn and even write some in college so I have a slight heading on where to start. I figure we can objdump the binary to a file and grep through the assembly looking for a cmp instruction.
Looking at the cmp instruction and the surrodning instructions could give away the spot where the conditional is checking for the passcode. Of course since the binary is stripped, it is going to be quite the ridiculous garbled output.

 520   4007ed:   55                      push   %rbp
 521   4007ee:   48 89 e5                mov    %rsp,%rbp
 522   4007f1:   48 83 ec 20             sub    $0x20,%rsp
 523   4007f5:   89 7d ec                mov    %edi,-0x14(%rbp)
 524   4007f8:   b8 00 00 00 00          mov    $0x0,%eax
 525   4007fd:   e8 7b ff ff ff          callq  40077d <dlsym@plt+0xfd>
 526   400802:   bf e8 08 40 00          mov    $0x4008e8,%edi
 527   400807:   e8 04 fe ff ff          callq  400610 <puts@plt>
 528   40080c:   48 8d 45 fc             lea    -0x4(%rbp),%rax
 529   400810:   48 89 c6                mov    %rax,%rsi
 530   400813:   bf 07 09 40 00          mov    $0x400907,%edi
 531   400818:   b8 00 00 00 00          mov    $0x0,%eax
 532   40081d:   e8 3e fe ff ff          callq  400660 <__isoc99_scanf@plt>
 533   400822:   8b 45 fc                mov    -0x4(%rbp),%eax
 534   400825:   3d 8f 01 00 00          cmp    $0x18f,%eax
 535   40082a:   74 11                   je     40083d <dlsym@plt+0x1bd>
 536   40082c:   bf 0a 09 40 00          mov    $0x40090a,%edi
 537   400831:   e8 da fd ff ff          callq  400610 <puts@plt>
 538   400836:   b8 00 00 00 00          mov    $0x0,%eax
 539   40083b:   eb 0f                   jmp    40084c <dlsym@plt+0x1cc>
 540   40083d:   bf 0f 09 40 00          mov    $0x40090f,%edi
 541   400842:   e8 c9 fd ff ff          callq  400610 <puts@plt>
 542   400847:   b8 00 00 00 00          mov    $0x0,%eax</

The assembly code was quite massive with over 1033 lines but I managed to ferret out the above block as one warranting closer examination. Simply because puts and scanf caught my eye. Looking two below the scanf(532) we have cmp at 534. The first value 0x18f is compared against whatever is at %eax. 533 is a mov that takes our value and pushes it to %eax so we can conclude our value at %eax is compared against 0x18f. A quick hex to base 10 conversion reveals 0x18f to be 399. Lets give it a try.

user@ubuntu:~$ ./pwd2
Please supply 3 digit passcode
399
Win.

Conclusion

It worked but Im quite fortunate in the fact that puts and scanf werent also put under dlsym as that wouldve made it a good bit harder to identify.

Additionally Im fortunate in that the passcode was stored simply and not obfuscated any further.

It was a fun challenge and Im looking forward to doing more of these

All and all a great foray into the world of RE.

Share on

Anthony Laiuppa
WRITTEN BY
Anthony Laiuppa
DevSecOps Engineer