Software Reverse Engineering: Diffusing Phase 4

Abhinav Thakur
5 min readApr 11, 2022

--

Baby, I hate little secrets you keep from me x_x

The article continues the previous one where we diffused phase 3 of bomb binary. Let’s get started with phase 4 on Windows platform using Windbg.

This writeup is a part of the article series —

Rescue Mission: Phase_4

Looking at the disassembly for phase_4() (uf bomb!phase_4). We see sscanf() call exactly the same way as in phase_3() , i.e. expecting 2 integers. Therefore, we’ll be following an initial approach similar to previous phase.

uf phase_4
0:001> da 00007ff6`0377c220
00007ff6`0377c220 "%d %d"

Validating user input

Let’s statically analyze how it validates user input.

0:001> uf phase_4
...
135 00007ff6`037723c1 cmp dword ptr [rbp+4],0
135 00007ff6`037723c5 jl bomb!phase_4+0x7d (00007ff6`037723cd)
135 00007ff6`037723c7 cmp dword ptr [rbp+4],0Eh
135 00007ff6`037723cb jle bomb!phase_4+0x82 (00007ff6`037723d2)
136 00007ff6`037723cd call bomb!ILT+945(explode_bomb)
...

This simply says that user input should be — 0 < [rbp+4] < 0xe (14) (where [rbp+4] is first integer of user input) for bomb to not explode.

Next, we see a call to func4() whose return value decides whether bomb explodes or not.

call site of func4()
  • 0x00007ff6`037723e9 to 0x00007ff6`037723f2 : return value (in eax) is checked against [rbp+64] (first integer input), if it isn’t equal explode_bomb() is called.
  • 00007ff6`037723f4 to 00007ff6`037723fa : explodes bomb if [rbp+24] (second integer input) is not equal to [rbp+64]. We have to peek into rpb+64 to find out this value.
0:000> dd rbp+64 L1
00000038`b74ff974 0000000a

Therefore, we are sure that the correct value for second integer in input string is 10. The question is how can we make func4() return a value of 0xa ?

Analyzing func4

Let’s analyze what parameters it takes by stepping to call instruction for func4().

0:001> pa 00007ff6`037723e4
0:000> r rcx, rdx, r8
rcx=0000000000000002 rdx=0000000000000000 r8=000000000000000e

which makes function prototype for func4 to be —

int func4 (my_int, a, b);         // a = 0, b = 0xe
uf func4

This function references its parameters via RBP, a stack diagram therefore would give us more clarity over what it refers.

Therefore, [rbp+100] is first parameter, whereas [rbp+108] and [rbp+110] are second and third parameter. First part of the disassembly does some math which should make sense after understanding the stack diagram —

some math
eax = (((signed qword typecast)(b - a)) - a)/2;
*(rbp+4) = ecx = a + eax

[rbp+4] is then compared to first parameter of func4() (i.e. first integer in our input string). Accordingly, the corresponding block of code is executed.

121 00007ff6`03771f75   cmp    dword ptr [rbp+4],eax
121 00007ff6`03771f78 jle bomb!func4+0x8a (00007ff6`03771f9a)

...
123 00007ff6`03771f9a mov eax,dword ptr [rbp+100h]
123 00007ff6`03771fa0 cmp dword ptr [rbp+4],eax
123 00007ff6`03771fa3 jge bomb!func4+0xb5 (00007ff6`03771fc5)
else
124 00007ff6`03771fa5 mov eax,dword ptr [rbp+4]
124 00007ff6`03771fa8 inc eax
124 00007ff6`03771faa mov r8d,dword ptr [rbp+110h]
124 00007ff6`03771fb1 mov edx,eax
124 00007ff6`03771fb3 mov ecx,dword ptr [rbp+100h]
124 00007ff6`03771fb9 call bomb!ILT+725(func4) (00007ff6`037712da)
124 00007ff6`03771fbe add eax,dword ptr [rbp+4]
124 00007ff6`03771fc1 jmp bomb!func4+0xb8 (00007ff6`03771fc8)
...
126 00007ff6`03771fc5 mov eax,dword ptr [rbp+4] // BASE CASE
127 00007ff6`03771fc8 lea rsp,[rbp+0E8h]
127 00007ff6`03771fcf pop rdi
127 00007ff6`03771fd0 pop rbp
127 00007ff6`03771fd1 ret
func4() base case and if code construct

Disassembly code for else case is as follows —

122 00007ff6`03771f7a  mov     eax,dword ptr [rbp+4]
122 00007ff6`03771f7d dec eax
122 00007ff6`03771f7f mov r8d,eax
122 00007ff6`03771f82 mov edx,dword ptr [rbp+108h]
122 00007ff6`03771f88 mov ecx,dword ptr [rbp+100h]
122 00007ff6`03771f8e call bomb!ILT+725(func4) (00007ff6`037712da)
122 00007ff6`03771f93 add eax,dword ptr [rbp+4]
122 00007ff6`03771f96 jmp bomb!func4+0xb8 (00007ff6`03771fc8)
...
127 00007ff6`03771fc8 lea rsp,[rbp+0E8h]
127 00007ff6`03771fcf pop rdi
127 00007ff6`03771fd0 pop rbp
127 00007ff6`03771fd1 ret
func4() else code construct

Therefore, final pseudocode for func4 becomes —

Pseudocode for func4()

NOTE: Disassembly of func4() for Linux version of bomb binary differs a bit from this one (generated by Microsoft’s VS compiler). You can find the pseudocode crafted for Linux version of bomb here.

Understanding Reccursive Calls

Below are a few attributes I observed while analyzing this function —

  • There is a reccursive call to func4() with distinct 2nd and 3rd parameter (a and b) but constant 1st parameter (first integer from our input string).
  • Base case for reccursion here is: *(rbp+4) == my_int .
  • Mathematically the expression —((b-a)-a)/2 + a is evaluated (and stored in *(rbp+4))and compared with my_int . Depending on the value of my_int , the control flow is transfered for next func4() call.
  • Value inside a & b can be controlled via value in my_int .

Initially, the expression evaluates to a value of 7. My initial approach was to create a call tree to find a pattern , but as I created the first level …

func4 (x, 0, 14) [expr = 7 (i.e. (14-0-0)/2 + 0)]
|
|
|-> if(x > 7): call func4(x, 7+1, 14): [expr = 7 (i.e. (14-16)/2+8)]
|
|-> if(x < 7): call func4(x, 0, 7-1): [expr = 3 (i.e. (6-0)/2+0)]

The second level (when x < 7) returns us a value of 3, if we provide an integer of 3 as input it will fall into the base case (i.e. x == expr). The return value of 3 when added to initial evaluation of expression, i.e. 7 returns a value of 10(i.e. eax += *(rbp+4); return eax; in the end of our func4() pseudocode) as needed by phase_4(). Let’s try a value of 3 as our input.

phase_4 diffused

Epilogue

Phase 4 was interesting as it involved reverse engineering simple mathematical expressions, if-else code constructs, reccursion and drawing stack diagram as done for func4()'s stack frame. Let’s continue right into the writeup for diffusing phase_5.

Cheers,
Abhinav Thakur
(a.k.a
compilepeace)

Connect on Linkedin

--

--