syncopation HTB business ctf

Table of Contents

Syncopation

This is a challenge from the HTB Business CTF in July 2021.

The user has to enter a “killswitch”, when this switch is correct, it is equivalent to the flag.

The challenge was solved using binary ninja in the normal graph disassembly view. At the end of the article there is also a high level IL view of the flag comparison function.

This is a very short first post for this blog and hopefully not too many details are left out.


After reading in the user input a comparison function at 0x400677 is called to compare the stored flag with the user input.

main

The cyan colored blocks have one real instruction and the rest is for moving forward inside the code. These instructions are colored orange in the screenshot. On the right hand side of the first screenshot the high level graph view of this function is visible. In that view most code is marked as cyan while part is marked as orange and only the orange parts are really relevant tot the challenge. These orange lines will be later extracted as separate code for easier readability. cyan1

This next screenshot shows the end of the cyan blocks and the comparison block (a lot of cyan single instruction block have been left out). cyan2

The jump construct

Add ida picture and describe it

Extracting only the orange lines results in the following code for the loop(some annotations included):

GET THE CURRENT CHAR IN USER INPUT 
eax, dword ptr [rbp-0x34 {index}]
movsxd  rdx, eax
mov     rax, qword ptr [rbp-0x48 {userInput}]
add     rax, rdx
movzx   eax, byte ptr [rax]
mov     byte ptr [rbp-0x36 {currentUserInputChar}], al

GET CURRENT CHAR IN FLAG BLOCK
mov     edx, dword ptr [rbp-0x34 {index}]
mov     eax, edx
shl     eax, 0x2  // index = index * 4
add     eax, edx  // index = index + index = index * 4 + index = 5 * index
movzx   eax, byte ptr [rax+0x400a00]  // load address of stored flag block
mov     byte ptr [rbp-0x35 {checkBlockChar}], al

COMPARE THE CHARS
movzx   eax, byte ptr [rbp-0x36 {currentUserInputChar}]
cmp     al, byte ptr [rbp-0x35 {checkBlockChar}]
jz      0x400807   // restart loop and increase index by one

What can be seen from the code above is, that it gets the character at the current index for the user input and for the flag. Those two characters are than compared, if they are identical the loop continues until all characters have been compared, otherwise the comparison ends.

As an addition here is a high level IL view from binary ninja: high_level

This high level view also makes it clear that there is a loop of lenght 0x1d that compares the user_input[index] to the flag_block[5*index]. (The flag_block starts at 0x400a00)

The referenced flag block looks like the following hex: flag_block

Flag

Taking every 5th character out of this with a loop of 0x1d(29 decimal) results in the following string: HTB{4_r4th3r_0ffb34t_b1n4ry!}