---
### Challenge Description
For the extreme-level challenge, submit your walkthrough (or link to it) as well as the solution. The judges will review submissions at least once a day. Good luck!
---
### Summary
In this challenge, the objective is to reverse-engineer a binary to extract an encrypted flag. The program employs RC4 encryption, multithreading, and various anti-debugging techniques. The primary goals are to patch the `win` function to decrypt the encrypted flag -- instead of encrypting the input -- and to modify the `encrypt` function to bypass anti-debugging checks. After applying these patches and debugging the program, the decrypted flag becomes visible on the stack.
---
### Understand the Program
Note: Some function and variable names have been changed to enhance the reader's understanding of the program flow.
###### main
^abdeb5
![[images/Pasted image 20230904144927.png]]
Important details:
- Lines 6 and 7 enable multithreading in the program
- Line 8 and 9 are anti-debugging techniques, that ultimately don't end up doing anything(described later)
- The function requires a command line argument
###### win
^59850e
![[images/Pasted image 20230904145318.png]]
![[images/Pasted image 20230904174546.png]]
Important details:
- The encrypted flag is stored in `enc_flag`
- The for loop on line 69 reads the values from `argv[1]`, and stores each byte of the flag into the local variable v2 (line 70), and each contiguous variable in memory
- The flag is encrypted with the `encrypt` function
###### encrypt
^a55152
![[images/Pasted image 20230904174107.png]]
Important details:
- On line 39, the RC4 Key-Scheduling algorithm is ran.
- During the for loop starting on line 40, the RC4 Pseudo-Random Generation Algorithm is ran 8192 times.
- Note that there is a `sleep(0);` function call each loop iteration, this is another anti-debugging feature.
- Line 42 checks if the result of the `getTickCount();` call equals 1 (another anti-debugging technique)
- On the for loop starting on line 48, the flag is XOR'd, resulting in the encryption of the flag.
---
### Patch the `win` Function
After doing some research on RC4, I discovered that encrypting a RC4 encrypted string is the equivalent of decrypting it, due to the nature of the xor function. We need to modify the `win` function to use the `enc_flag` array, so the program decrypts the flag, instead of encrypting our input.
**main**
![[images/Pasted image 20230904150744.png]]
Here is the corresponding assembly code:
![[images/Pasted image 20230904152011.png]]
Modifying the loop in [[#^abdeb5|main]] to use `enc_flag` can be accomplished by patching the bytes with IDA's Assemble feature.
First, click `inp_flag` in the assembly view.
Then, go to Edit-->Patch Program-->Assemble
![[images/Pasted image 20230904152500.png]]
(Note, you must use a `lea` instruction, as you need to reference the *memory address* of a *local variable*, not the actual value stored in `[ebp+enc_flag]`).
The disassembly should look like this:
![[images/Pasted image 20230904152627.png]]
---
### Patch the `encrypt` Function
This loop in the [[#^a55152|encrypt]] function is causing us some issues:
![[images/Pasted image 20230904160330.png]]
As a reminder, the result of the `getTickCount()` function is put into `tick_count_1`. Since debugging a program usually results in this value being much larger than if it ran naturally, we need to patch the for loop to skip checking if `dword_4244C4` is 0.
![[images/Pasted image 20230904161447.png]]
This can be accomplished by modifying the highlighted `jz` instruction. Change it to unconditionally jump after the `cmp` instruction is ran:
Edit-->Patch Program-->Assemble
![[images/Pasted image 20230904161648.png]]
Your disassembly should look like this:
![[images/Pasted image 20230904161745.png]]
Finally, apply the patches we made.
Edit --> Patch Program --> Apply Patches to Input File![[images/Pasted image 20230904165411.png]]
---
### Debug the program
The [[#^abdeb5|main]] function requires a command line argument `(argv[1])`:
```c
if ( argc == 2 )
{
if ( win(argv[1]) )
{
printf("[+] You achieved level 12!\r\n");
uExitCode = 0;
}
```
Set the argument by going to Debugger-->Process Options:
![[images/Pasted image 20230904161918.png]]
Set a breakpoint on line 72 in the [[#^59850e|win]] function (right after decryption has occurred):
![[images/Pasted image 20230904165540.png]]
Hit `F9` to start the debugging process
Looking at the General Registers, it appears that `ESP` is pointing to the flag on the stack:
![[images/Pasted image 20230904170028.png]]
![[images/Pasted image 20230904165822.png]]
Hit `Shift+F12` to open strings to view the full flag:
![[images/Pasted image 20230904163028.png]]
Flag: `flag_{8079b1c9a4844ecd9e5d33dc6642d779}`