• In this note there are multiple IDEs and tools to perform reversing
  • Check IDA ๐Ÿ‘  notes

Analyzing functions

  • Sometimes you can find flags inside a function in plain text just by observing the Decompiler (open in Window >> Decompiler):


  • If you find a lot of variables predefined on a function as follows:

  • You can see that the first one is a char whereas the last one is a pointer. If we look at the dis-assembler section, we can get an idea about how these variables are added to the stack. We can clearly see a reverse order.

  • The last char pointer which isย local_8ย is the first one added to the stack as follows.
  • We can see that each variable is assigned a value as follows. The first char variable which isย local_2cย is assigned to โ€˜Fโ€™ and all the undefined variables are assigned hex values.

  • So now, we know that these hex values should be ASCII characters because each value is exactly one byte.
  • If you remember, we found that the last variable defined which is local_8, is a character pointer. Now, it is assigned to be aย hash of the stringย starting at the memory address of the variableย char local_2c, as follows.

  • This means that it will hash the entire string fromย bottom of the stackย toย top. Thus, we need toย convertย each hex character assigned for the variables afterย local_2cย into ASCII characters in order to obtain the string that is being hashed.
  • You can useย hex-to-ascii converterย for this purpose. You will be given the flag in ASCII.

  • As you can see, there are some external functions called such asย FindResourceA()ย andย LoadStringsA(). When we look at the assembly code, we can come across that FindResourceA() is from the Kernel32 Library and LoadStringsA() is from User32 Library.

  • What LoadStringsA() does is that it loads the string from its reference and stores at the variableย local_4a4.ย So, let us find the reference.
  • As shown in the above entry function, we know thatย 0x110ย hex value parameter is the identifier for the string in LoadStringsA() function call.
  • Hex 0x110 = Decimalย 272
  • Openย Defined Stringsย from Ghidra ribbon (Window >> Defined Strings). Scroll down and you will come across a FLAG table which contains many flags.

  • Take a look at the equivalent code on dis-assembler and you will find-out theย string-IDย at the far right corner in decimal. So, scroll down until you find the string-ID 272.


Using gdb when finding strcmp() function

gdb file
 
(gdb) info functions
 
0x00000000004004b0  _init
0x00000000004004e0  puts@plt
0x00000000004004f0  __stack_chk_fail@plt
0x0000000000400500  printf@plt
0x0000000000400510  __libc_start_main@plt
0x0000000000400520  strcmp@plt
0x0000000000400530  __gmon_start__@plt
0x0000000000400540  _start
0x0000000000400570  deregister_tm_clones
0x00000000004005a0  register_tm_clones
0x00000000004005e0  __do_global_dtors_aux
0x0000000000400600  frame_dummy
0x000000000040062d  get_pwd
0x000000000040067a  compare_pwd
0x0000000000400716  main
0x0000000000400760  __libc_csu_init
0x00000000004007d0  __libc_csu_fini
0x00000000004007d4  _fini
  • We are interested in the strcmp@plt function
  • Set a breakpoint at the memory address of this function and run the binary in gdb with some test input:
(gdb) b *0x0000000000400520
 
(gdb) run test
  • The binary is executed until it hits the breakpoint as seen in the image above. Next, I can view the current state of the registers with gdb:
(gdb) info registers
 
rax            0x7fffffffdd50      140737488346448
rbx            0x7fffffffdea8      140737488346792
rcx            0x11                17
rdx            0x7fffffffe245      140737488347717
rsi            0x7fffffffe245      140737488347717
rdi            0x7fffffffdd50      140737488346448
rbp            0x7fffffffdd70      0x7fffffffdd70
rsp            0x7fffffffdd38      0x7fffffffdd38
r8             0x4007d0            4196304
r9             0x7ffff7fcfaf0      140737353939696
r10            0x7ffff7fcb858      140737353922648
r11            0x7ffff7fe1f80      140737354014592
r12            0x0                 0
r13            0x7fffffffdec0      140737488346816
r14            0x0                 0
r15            0x7ffff7ffd000      140737354125312
rip            0x400520            0x400520 <strcmp@plt>
eflags         0x246               [ PF ZF IF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
  • Looking at the output above I can see the names of the registers, the registers value in hexadecimal format and the registers value in the format gdb thinks most appropriate (hex for pointers, decimal for the others). I can see that the general purpose registers rax and rdx have memory address values. I can use gdb to print the strings at these addresses:
(gdb) x/s 0x7fffffffdd50

Not known file architecture

  • If you perform file whatever.whatever and gives you this:
0x41haz-1640335532346.0x41haz: ELF 64-bit MSB *unknown arch 0x3e00* (SYSV)
  • unknown arch 0x3e00 means that the file has no architecture

  • MSB refers to the endianness of the file. Most significant bit first means that the most significant byte (bit) of multi-byte data is stored at the lowest memory address. This endianness is commonly used in big-endian architectures.

  • SYSV, ABI (Application Binary Interface) used in the ELF file. โ€œSYSVโ€ stands for System V, which is a standard Unix ABI used in many Linux/Unix systems.

  • Open the file in a hex editor like: hexeditor or online hexeditor and follow this trick:

  • Edit the sixth bit on the code:

  • Change the 02 by 01:

  • Now it can be detected:
$ file 0x41haz-1640335532346.0x41haz 
 
0x41haz-1640335532346.0x41haz: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6c9f2e85b64d4f12b91136ffb8e4c038f1dc6dcd, for GNU/Linux 3.2.0, stripped

Personal advices

  • If you find a code (maybe encrypted), try to reverse it because sometimes thatโ€™s the answer :D

Searching for env variables

ltrace FILE
 
getenv("admin")                                  = nil
puts("Not an Admin"Not an Admin
)                             = 13
+++ exited (status 0) +++
  • In this case, you can create an admin environment variable and set it to 1:
export admin=1