Hackvent 2019: Day 12

Hackvent 2019290

Challenge

HV19.12 back to basic

Introduction
Santa used his time machine to get a present from the past. get your rusty tools out of your cellar and solve this one!

Resources
HV19.12-BackToBasic.zip

Resources: HV19-Day12-BackToBasic.zip

Solution

We download the above zip file and find a Windows PE executable called BackToBasic.exe.
Upon opening the file we are prompted for some input but our input is always wrong.

Hackvent 2019 - Day 12 - Back to basics GUI

Initially, we open this file in IDA Pro and inspect it. Its a smallish executable that was originally written in Visual Basic.
We decide to complete this challenge using only static analysis. We use a combination of IDA Pro and another tool called VB Decompiler.
This decompiler was specifically designed to decompile Visual Basic code so its a good bet!

We get the following decompilation result:

Private Sub Text1_Change() '401F80
  Dim Me As Me
  Dim var_4C As Variant
  loc_00402072: var_48 = Text1.Text
  loc_004020A6: var_34 = var_48
  loc_00402228: var_ret_7 = (Mid(var_34, 1, 1) = &H401B20) And (Mid(var_34, 2, 1) = &H401B28) And (Mid(var_34, 3, 1) = &H401B30) And (Mid(var_34, 4, 1) = &H401B38)
  loc_00402235: var_1C0 = CBool(var_ret_7)
  loc_00402280: If var_1C0 Then
  loc_004022A2:   var_5C = Len(var_34)
  loc_004022B9:   If (var_5C = 33) Then
  loc_0040230D:     var_ret_8 = Len(var_34) - 1
  loc_0040232D:     For var_24 = 6 To var_ret_8 Step 1
  loc_00402339: 
  loc_0040233B:       If var_1D4 Then
  loc_00402375:         var_154 = Asc(CStr(Mid(var_34, CLng(var_24), 1)))
  loc_00402391:         call Xor(var_7C, var_15C, var_24, var_4C, Me, Me, %S_eax_S = CLng(%StkVar1), %x1 = Mid(%StkVar2, %StkVar3, %StkVar4), 00000002h)
  loc_00402398:         var_ret_A = CLng(Xor(var_7C, var_15C, var_24, var_4C, Me, Me, var_ret_A = CLng(%StkVar1), %x1 = Mid(%StkVar2, %StkVar3, %StkVar4), 00000002h))
  loc_004023C5:         var_44 = var_44 + Chr(var_ret_A)
  loc_00402400:       Next var_24
  loc_00402406:       GoTo loc_00402339
  loc_0040240B:     End If
  loc_00402433:     If (var_44 = "6klzic<=bPBtdvff'yFI Then
  loc_00402456:       Label1.Caption = "Status: correct"
  loc_00402477:     End If
  loc_00402481:     GoTo loc_00402574
  loc_00402486:   End If
  loc_004024A7:   Label1.Caption = "Status: wrong"
  loc_004024AE:   If var_4C < 0 Then
  loc_004024B0:     GoTo loc_004024DC
  loc_004024B2:   End If
  loc_004024D3:   Label1.Caption = "Status: wrong"
  loc_004024DA:   If var_4C >= 0 Then GoTo loc_004024EB
  loc_004024DC:   'Referenced from: 004024B0
  loc_004024E5:   var_4C = CheckObj(var_4C, global_00401B9C, 84)
  loc_004024EB: End If
  loc_004024F4: GoTo loc_00402479
  loc_00402573: Exit Sub
  loc_00402574: 'Referenced from: 00402481
End Sub

We clean this up a little by working through the variables making sense of it all:

Private Sub Text1_Change() '401F80
  Dim Me As Me
  Dim var_4C As Variant
  loc_00402072: input_text_orig = Text1.Text //Originally HV19
  loc_004020A6: input_text = input_text_orig
  loc_00402228: first_four_chars = (Mid(input_text, 1, 1) = &H401B20) And (Mid(input_text, 2, 1) = &H401B28) And (Mid(input_text, 3, 1) = &H401B30) And (Mid(input_text, 4, 1) = &H401B38)
  loc_00402235: is_bool = CBool(first_four_chars)
  loc_00402280: If is_bool Then
  loc_004022A2:   input_text_len = Len(input_text)
  loc_004022B9:   If (input_text_len = 33) Then
  loc_0040230D:     input_text_len_minus_1 = Len(input_text) - 1
  loc_0040232D:     For char_counter = 6 To input_text_len_minus_1 Step 1 // From chars 6 to 32 inclusive
  loc_00402339: 
  loc_0040233B:       If var_1D4 Then
  loc_00402375:         var_154 = Asc(CStr(Mid(input_text, CLng(char_counter), 1))) // Give the integer representation of the next character
  loc_00402391:         call Xor(var_7C, var_15C, char_counter, var_4C, Me, Me, %S_eax_S = CLng(%StkVar1), %x1 = Mid(%StkVar2, %StkVar3, %StkVar4), 00000002h)
  loc_00402398:         var_ret_A = CLng(Xor(var_7C, var_15C, char_counter, var_4C, Me, Me, var_ret_A = CLng(%StkVar1), %x1 = Mid(%StkVar2, %StkVar3, %StkVar4), 00000002h))
  loc_004023C5:         flag_content = flag_content + Chr(var_ret_A)
  loc_00402400:       Next char_counter // increment counter
  loc_00402406:       GoTo loc_00402339
  loc_0040240B:     End If
  loc_00402433:     If (flag_content = "6klzic<=bPBtdvff'yFI Then
  loc_00402456:       Label1.Caption = "Status: correct"
  loc_00402477:     End If
  loc_00402481:     GoTo loc_00402574
  loc_00402486:   End If
  loc_004024A7:   Label1.Caption = "Status: wrong"
  loc_004024AE:   If var_4C < 0 Then
  loc_004024B0:     GoTo loc_004024DC
  loc_004024B2:   End If
  loc_004024D3:   Label1.Caption = "Status: wrong"
  loc_004024DA:   If var_4C >= 0 Then GoTo loc_004024EB
  loc_004024DC:   'Referenced from: 004024B0
  loc_004024E5:   var_4C = CheckObj(var_4C, global_00401B9C, 84)
  loc_004024EB: End If
  loc_004024F4: GoTo loc_00402479
  loc_00402573: Exit Sub
  loc_00402574: 'Referenced from: 00402481
End Sub

After a while we understand what the code is basically doing.
Our input string is first checked to ensure the first 4 characters equal HV19. If this condition is met, we check that our input string has a length of 33 characters. If this condition is met, we perform a loop from 6 to 32 inclusive. These bounds are interesting as Visual Basic starts indexes at 1 and the first 5 characters of our flag are typically HV19{ and the last character is }. Basically we are looping over the indexes belonging to the flag content. Next, we seem to perform some XOR operation on the ordinal of the character (VB Asc command) and some other unknown value. It took a little time to realise this other value was the current string index (which I named char_counter above). Finally, a check is made with the string 6klzic<=bPBtdvff'yFI~on//N. It is important to note that the string is UTF-16 little endian encoded.

Therefore, we simply have to reverse the operation to get our original flag. In other words, take our comparison string 6klzic<=bPBtdvff'yFI~on//N and XOR it with the corresponding index (6,7,etc).

Pseudocode:

input = Text1.Text

test = ''
if input[1] = 'H' & input = 'V' & input = '1' & input = '9':
	if len(input) = 33:
		for i = 6 to i = 33 - 1:
			xor_res = ord(input[i]) ^ i
			test = test + chr(xor_res)
			
			
		if test == "6klzic<=bPBtdvff'yFI~on//N":
			print("Status: correct")
		else:
			print("Status: wrong")

We write a little python script to do this for us which provides us with our flag:

# Hackvent 2019 - Day 12
# Mo Beigi (https://mobeigi.com)

# Hex dump of comparison string UTF-16 little endian encoded
# UTF-16: 6klzic<=bPBtdvff'yFI~on//N
comp_string = b'\x36\x00\x6B\x00\x6C\x00\x7A\x00\x69\x00\x63\x00\x3C\x00\x3D\x00\x62\x00\x50\x00\x42\x00\x74\x00\x64\x00\x76\x00\x66\x00\x66\x00\x27\x00\x79\x00\x7F\x00\x46\x00\x49\x00\x7E\x00\x6F\x00\x6E\x00\x2F\x00\x2F\x00\x4E\x00'

flag_content = ''
for index, val in enumerate(comp_string.decode('utf-16')):
    xor_val = ord(val) ^ index + 1 + len('HV19{') # VB indices start at 1
    flag_content += chr(xor_val)

# Print final flag
flag = 'HV19{' + flag_content + '}'
print(flag)

Flag:

HV19{0ldsch00l_Revers1ng_Sess10n}

Leave a comment

(required)(will not be published)(required)

Comments

There are no comments yet. Be the first to add one!