tkh4ck.github.io

Personal website and blog of tkh4ck

View on GitHub

HCSC 2024 - Patch Adams

Description

Kérlek kezdd a megoldást a Tutoriallal! Ott vannak leírva a fontos infók!

Üdvözlet bajnokom! Ásót, kapát, kalapácsot elő, visszafejtésre fel! Számtalan hasznos eszköz lapul egy igazán jó hacker eszköztárában. Van nekünk ghidránk, IDA-nk, binutils-unk, gdb-nk, radare2-nk ésatöbbi. Nincs jó hacker radare2 tudás nélkül. Hogy ne unatkozz, össze is dobtam Neked egy környezetet, ahol kiélheted minden reverse engineering vágyad, amiről eddig csak álmodtál. Nézzük, hogy megtalálod-e a flaget!

A feladat forráskódjának egy részét csatoltuk! Jelenlegi main.go sha256sum: 6dcbb947247ef67fe3ddf30fd441f624b13bb0b058e4f6a6fee2815344e5f2da

Flag formátum: HCSC24{...}

Köszönet kocka-nak a radare2 inspirációért!

By MJ

Hint 1 (cost 100): Nincs valami fv, ami kiolvasná a flaget?

Metadata

Solution

We have a website and a main.go file. Through the website we can send two radare2 commands, which is executed by the server on a binary. Then the server runs the binary.

Main page

The important parts of main.go are the following:

r2Commands := []string{
    "oo+",
    "e cfg.sandbox=all", // idea from pancake
    "aaaa",
    fmt.Sprintf("%s %s", command1, argument1),
    fmt.Sprintf("%s %s", command2, argument2),
}
[...]
randomName := fmt.Sprintf("/tmp/adams_%d", rand.Intn(10000))
err := copyFile("adams", randomName)
[...]
r2Output, err := executeR2Commands(randomName, r2Commands)
[...]
cmd := exec.Command(randomName)
cmd.Stderr = os.Stderr
output, err := cmd.Output()

First, we want to understand the adams binary. We can get the complete disassembly of the binary using pd, but first seek to 0x00:

$ curl 'http://193.225.251.158:41670/' -d 'command1=s' -d 'argument1=0x00' -d 'command2=pd' -d 'argument2=0xffff'

The dump is available at: adams.asm

The interesting parts are around 0x00001000 (.text) and 0x00002000 (.rodata).

The binary always gives Unauthorized output:

Final Binary Output:
Unauthorized

Using the iz command, or the dump, we can check the strings in the binary, there is a /secret/flag.txt @ 0x00002577:

0   0x00002000 0x00002000 12  13   .rodata ascii Unauthorized
1   0x00002010 0x00002010 116 117  .rodata ascii You treat a disease, you win, you lose. You treat a person, I guarantee you, you'll win, no matter what the outcome.
2   0x00002088 0x00002088 271 272  .rodata ascii I love you without knowing how, or when, or from where. I love you straightforwardly without complexities or pride. I love you because I know no other way then this. So close that your hand, on my chest, is my hand. So close, that when you close your eyes, I fall asleep.
3   0x00002198 0x00002198 66  67   .rodata ascii Our job is improving the quality of life, not just delaying death.
4   0x000021e0 0x000021e0 116 117  .rodata ascii You're focusing on the problem. If you focus on the problem, you can't see the solution. Never focus on the problem!
5   0x00002258 0x00002258 319 320  .rodata ascii What's wrong with death sir? What are we so mortally afraid of? Why can't we treat death with a certain amount of humanity and dignity, and decency, and God forbid, maybe even humor. Death is not the enemy gentlemen. If we're going to fight a disease, let's fight one of the most terrible diseases of all, indifference.
6   0x00002398 0x00002398 138 139  .rodata ascii See what no one else sees. See what everyone chooses not to see... out of fear, conformity or laziness. See the whole world anew each day!
7   0x00002428 0x00002428 73  74   .rodata ascii We can head on down to the maternity ward. You know those chicks put out.
8   0x00002478 0x00002478 60  61   .rodata ascii We need to start treating the patient as well as the disease
9   0x000024b8 0x000024b8 128 129  .rodata ascii I wanted to become a doctor so I could serve others. And because of that, I've lost everything. But I've also gained everything.
10  0x0000253b 0x0000253b 13  14   .rodata ascii /etc/hostname
11  0x0000254c 0x0000254c 8   9    .rodata ascii adams-pc
12  0x00002558 0x00002558 30  31   .rodata ascii Error: /etc/hostname not found
13  0x00002577 0x00002577 16  17   .rodata ascii /secret/flag.txt
14  0x00002588 0x00002588 25  26   .rodata ascii Error: flag.txt not found

The fcn.0000142d function calls fcn.00001215 at the end, which prints the Unauthorized message

/ 22: fcn.00001215 ();
|           0x00001215      55             push rbp
|           0x00001216      4889e5         mov rbp, rsp
|           0x00001219      488d05e00d00.  lea rax, str.Unauthorized   ; segment.LOAD2
|                                                                      ; 0x2000 ; "Unauthorized"
|           0x00001220      4889c7         mov rdi, rax                ; const char *s
|           0x00001223      e818feffff     call sym.imp.puts           ; int puts(const char *s)
|           0x00001228      90             nop
|           0x00001229      5d             pop rbp
\           0x0000122a      c3             ret
[...]
/ 72: fcn.0000142d ();
|           0x0000142d      55             push rbp
|           0x0000142e      4889e5         mov rbp, rsp
|           0x00001431      bf00000000     mov edi, 0
|           0x00001436      e865fcffff     call sym.imp.time           ; time_t time(time_t *timer)
|           0x0000143b      89c7           mov edi, eax
|           0x0000143d      e83efcffff     call sym.imp.srand          ; void srand(int seed)
|           0x00001442      b800000000     mov eax, 0
|           0x00001447      e8a0feffff     call fcn.000012ec
|           0x0000144c      84c0           test al, al
|           0x0000144e      7414           je 0x1464
|           0x00001450      b800000000     mov eax, 0
|           0x00001455      e8d1fdffff     call fcn.0000122b
|           0x0000145a      4889c7         mov rdi, rax
|           0x0000145d      e8defbffff     call sym.imp.puts           ; int puts(const char *s)
|           0x00001462      eb0a           jmp 0x146e
|           ; CODE XREF from fcn.0000142d @ 0x144e(x)
|           0x00001464      b800000000     mov eax, 0
|           0x00001469      e8a7fdffff     call fcn.00001215
|           ; CODE XREF from fcn.0000142d @ 0x1462(x)
|           0x0000146e      b800000000     mov eax, 0
|           0x00001473      5d             pop rbp
\           0x00001474      c3             ret

However, there is a function which reads /secret/flag.txt and outputs the content (fcn.0000139d).

/ 144: fcn.0000139d ();
|           ; var int64_t var_8h @ rbp-0x8
|           ; var int64_t var_70h @ rbp-0x70
|           ; var int64_t var_78h @ rbp-0x78
|           0x0000139d      55             push rbp
|           0x0000139e      4889e5         mov rbp, rsp
|           0x000013a1      4883c480       add rsp, 0xffffffffffffff80
|           0x000013a5      64488b042528.  mov rax, qword fs:[0x28]
|           0x000013ae      488945f8       mov qword [var_8h], rax
|           0x000013b2      31c0           xor eax, eax
|           0x000013b4      488d057e1100.  lea rax, [0x00002539]       ; "r"
|           0x000013bb      4889c6         mov rsi, rax
|           0x000013be      488d05b21100.  lea rax, str._secret_flag.txt ; 0x2577 ; "/secret/flag.txt"
|           0x000013c5      4889c7         mov rdi, rax
|           0x000013c8      e8a3fcffff     call sym.imp.fopen          ; file*fopen(const char *filename, const char *mode)
|           0x000013cd      48894588       mov qword [var_78h], rax
|           0x000013d1      48837d8800     cmp qword [var_78h], 0
|           0x000013d6      742f           je 0x1407
|           0x000013d8      488b5588       mov rdx, qword [var_78h]
|           0x000013dc      488d4590       lea rax, [var_70h]
|           0x000013e0      be64000000     mov esi, 0x64               ; 'd'
|           0x000013e5      4889c7         mov rdi, rax
|           0x000013e8      e843fcffff     call sym.imp.fgets          ; char *fgets(char *s, int size, FILE *stream)
|           0x000013ed      488d4590       lea rax, [var_70h]
|           0x000013f1      4889c7         mov rdi, rax
|           0x000013f4      e847fcffff     call sym.imp.puts           ; int puts(const char *s)
|           0x000013f9      488b4588       mov rax, qword [var_78h]
|           0x000013fd      4889c7         mov rdi, rax
|           0x00001400      e88bfcffff     call sym.imp.fclose         ; int fclose(FILE *stream)
|           0x00001405      eb0f           jmp 0x1416
|           ; CODE XREF from fcn.0000139d @ 0x13d6(x)
|           0x00001407      488d057a1100.  lea rax, str.Error:_flag.txt_not_found ; 0x2588 ; "Error: flag.txt not found"
|           0x0000140e      4889c7         mov rdi, rax
|           0x00001411      e82afcffff     call sym.imp.puts           ; int puts(const char *s)
|           ; CODE XREF from fcn.0000139d @ 0x1405(x)
|           0x00001416      90             nop
|           0x00001417      488b45f8       mov rax, qword [var_8h]
|           0x0000141b      64482b042528.  sub rax, qword fs:[0x28]
|           0x00001424      7405           je 0x142b
|           0x00001426      e825fcffff     call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|           ; CODE XREF from fcn.0000139d @ 0x1424(x)
|           0x0000142b      c9             leave
\           0x0000142c      c3             ret

Our solution can be patching 0x00001469 call fcn.00001215 so that it is 0x00001469 call fcn.0000139d.

This can be done with s (seek) and w (write) for example:

s 0x0000146a
wv 0xffffff2f

or

s 0x1469
wa call 0x139d
$ curl 'http://193.225.251.158:41670/' -d 'command1=s' -d 'argument1=0x0000146a' -d 'command2=wv' -d 'argument2=0xffffff2f'
$ curl 'http://193.225.251.158:41670/' -d 'command1=s' -d 'argument1=0x1469' -d 'command2=wa' -d 'argument2=call 0x139d'

The official write-up by MJ is available at: https://github.com/NIK-SOC/hcsc_2024_mj/tree/main/ctf-patch_adams

Flag: HCSC24{d0ct0r_0r_nOt_U_r3c0v3r3d_7h3_fl4g}