Damn Windows
This is a writeup of the reversing challenge damn windows from the Security Valley CTF
Level: 3, Score: 40
Premise
There is some exotic compiled windows executable.Can you deal with it?
Link: https://github.com/SecurityValley/PublicCTFChallenges/tree/master/reversing/damn_windows
Challenge files:
01.exe
Observations
Simply running the program gives us the following output:
1
2
can you deal with a more complex language then C?
please enter the password
So we try the password test
, which gives us the output:
1
2
test
2023/07/27 21:53:26 wrong password kid
So no luck.
Fiddling around with the input doesn’t yield any results, so now another method is required.
Solution
If we investigate the file in the tool Exeinfo PE, it tells us that the program is written in GOlang. Moving forwards, we open the program in ghidra, run its analyzer and investigate further. At a glance, we find ourselves having a hard time getting further, but if we run the GO function renamer script for ghidra written by Dorka Patolay, we’re able to investigate more easily.
If we look at the main.main function, we find the following content:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
void main.main(void)
{
undefined8 extraout_RAX;
undefined8 extraout_RAX_00;
undefined8 uVar1;
int extraout_RCX;
int extraout_RCX_00;
undefined8 extraout_RBX;
undefined8 extraout_RBX_00;
undefined8 uVar2;
undefined8 extraout_RDI;
undefined auVar3 [16];
undefined auVar4 [16];
undefined8 local_118;
int local_110;
undefined8 local_108;
undefined8 local_100;
undefined local_f8 [16];
undefined local_e8 [16];
undefined local_d8 [16];
undefined local_c8 [16];
undefined local_b8 [16];
undefined8 local_a8;
runtime.itab *local_a0;
undefined8 local_98;
undefined8 local_70;
undefined8 local_68;
undefined local_60 [88];
auVar3 = (undefined [16])0x0;
while (local_c8 + 8 <= CURRENT_G.stackguard0) {
runtime.morestack_noctxt();
}
local_d8._8_8_ = &PTR_DAT_004d37f8;
local_d8._0_8_ = &string___runtime._type;
fmt.Fprintln(&go.itab.*os.File,io.Writer,os.Stdout,local_d8,1,1);
local_e8._8_8_ = &PTR_DAT_004d3808;
local_e8._0_8_ = &string___runtime._type;
fmt.Fprintln(&go.itab.*os.File,io.Writer,os.Stdout,local_e8,1,1);
local_100 = os.Stdin;
local_60._0_16_ = auVar3;
FUN_0045d0d0();
runtime.makeslice(&uint8___runtime._type,0x1000,0x1000);
local_b8 = auVar3;
local_b8._0_8_ = FUN_0045d0d0();
local_b8._8_8_ = 0x1000;
local_a8 = 0x1000;
local_a0 = &go.itab.*os.File,io.Reader;
local_98 = local_100;
local_70 = 0xffffffffffffffff;
local_68 = 0xffffffffffffffff;
local_60._0_8_ = local_b8._0_8_;
FUN_0045d43a();
bufio.(*Reader).ReadString(local_60,10);
local_110 = extraout_RCX;
auVar4 = strings.TrimRight(extraout_RAX,extraout_RBX,&DAT_004afbcc,2);
if (local_110 == 0) {
main.(*PasswordService).Validate(&local_118,auVar4._0_8_,auVar4._8_8_);
uVar1 = extraout_RAX_00;
uVar2 = extraout_RBX_00;
if (extraout_RCX_00 != 0) {
local_118 = extraout_RBX_00;
local_108 = extraout_RAX_00;
(**(code **)(extraout_RCX_00 + 0x18))(extraout_RDI);
local_c8 = auVar3;
local_c8._8_8_ = runtime.convTstring();
local_c8._0_8_ = &string___runtime._type;
log.Fatal(local_c8,1,1);
uVar1 = local_108;
uVar2 = local_118;
}
local_f8 = auVar3;
local_f8._8_8_ = runtime.convTstring(uVar1,uVar2);
local_f8._0_8_ = &string___runtime._type;
fmt.Fprintln(&go.itab.*os.File,io.Writer,os.Stdout,local_f8,1,1);
}
bufio.(*Reader).ReadString(local_60,10);
return;
}
We find the string:
1
main.(*PasswordService).Validate(&local_118,auVar4._0_8_,auVar4._8_8_);
Which we investigate further. Going to this function, we find the following content:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
undefined [32] main.(*PasswordService).Validate(undefined8 param_1,undefined8 param_2,int param_3)
{
char cVar1;
int iVar2;
undefined8 *puVar3;
undefined auVar4 [32];
undefined auVar5 [16];
undefined8 param_11;
undefined local_48 [16];
undefined local_38 [16];
undefined local_28 [16];
undefined local_18 [16];
while (param_11 = param_2, local_18 + 8 <= CURRENT_G.stackguard0) {
runtime.morestack_noctxt();
param_2 = param_11;
}
local_48._8_8_ = 6;
local_48._0_8_ = &DAT_004b00a8;
local_38._8_8_ = 1;
local_38._0_8_ = &DAT_004afb6e;
local_28._8_8_ = 0xc;
local_28._0_8_ = &DAT_004b1275;
local_18._8_8_ = 1;
local_18._0_8_ = &DAT_004afb6f;
auVar5 = strings.Join(local_48,4,4,0,0);
if ((auVar5._8_8_ == param_3) && (cVar1 = runtime.memequal(param_2,auVar5._0_8_), cVar1 != '\0'))
{
iVar2 = 0;
}
else {
iVar2 = runtime.cmpstring(param_2,param_3,auVar5._0_8_,auVar5._8_8_);
if (iVar2 < 0) {
iVar2 = -1;
}
else {
iVar2 = 1;
}
}
if (iVar2 != 0) {
puVar3 = (undefined8 *)runtime.newobject(&errors.errorString___runtime.structtype);
puVar3[1] = 0x12;
*puVar3 = &DAT_004b26d7;
auVar4._0_16_ = ZEXT816(0);
auVar4._16_8_ = &go.itab.*errors.errorString,error;
auVar4._24_8_ = puVar3;
return auVar4;
}
return ZEXT1632(CONCAT88(8,&DAT_004b04ef));
}
The 8 sections named local_18
, local_28
, local_38
and local_48
with a trailing 0 or 8 point to specific data sections, we can follow the top one of these, that being local_48
which points to DAT_004b00a8
. Here we find the following content:
1
2
3
4
5
6
7
8
DAT_004b00a8 XREF[2]: main.(*PasswordService).Validate
main.(*PasswordService).Validate
004b00a8 53 ?? 53h S
004b00a9 65 ?? 65h e
004b00aa 63 ?? 63h c
004b00ab 56 ?? 56h V
004b00ac 61 ?? 61h a
004b00ad 6c ?? 6Ch l
Which contains the first part required for our flag. If we keep looking at these reference points, we additionally find the left curly brace for our flag form the local_38._0_8_
variable
1
2
3
4
5
DAT_004afb6e XREF[3]:
runtime.printArgs:00452cc5(*),
main.(*PasswordService).Validate
004afb6e 7b ?? 7Bh {
and the right curly brace for our flag from the local_18._0_8_
variable
1
2
3
4
5
DAT_004afb6f XREF[3]:
runtime.printArgs:00452d99(*),
main.(*PasswordService).Validate
004afb6f 7d ?? 7Dh }
Now the string stored in the local_28._0_8_
variable contain our flag, so I will refrain from showing its content here.
However, if the flag is entered into the 01.exe file, the full conversation looks like this:
1
2
3
4
5
6
can you deal with a more complex language then C?
please enter the password
SecVal{[REDACTED]}
correct!