Skip to content

Commit

Permalink
Add UniCTF Quals 2021
Browse files Browse the repository at this point in the history
  • Loading branch information
skyf0l committed Nov 27, 2021
1 parent 291f8c6 commit a1d79dc
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# CTF
Some write-ups

## UniCTF Quals 2021

Fri, 19 Mov. 2021 — Sun, 21 Mov. 2021

**Ranked 21th on 594**

[Write-ups](UniCTF_Quals_2021/README.md)

## PicoCTF 2020

Tue, 16 Mar. 2021 — Tue, 30 Mar. 2021
Expand Down
5 changes: 5 additions & 0 deletions UniCTF_Quals_2021/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# UniCTF Quals 2021

Fri, 19 Mov. 2021 — Sun, 21 Mov. 2021

**Ranked 21th on 594**
Binary file not shown.
43 changes: 43 additions & 0 deletions UniCTF_Quals_2021/Reverse/PneumaticValidator/solve.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
2021-11-22 16:38:21,815 - INFO - Char 1/20: H (H...................)
2021-11-22 16:39:03,947 - INFO - Char 2/20: T (HT..................)
2021-11-22 16:39:46,090 - INFO - Char 3/20: B (HTB.................)
2021-11-22 16:40:27,844 - INFO - Char 4/20: { (HTB{................)
2021-11-22 16:41:09,142 - INFO - Char 5/20: P (HTB{P...............)
2021-11-22 16:41:50,735 - INFO - Char 6/20: N (HTB{PN..............)
2021-11-22 16:42:31,997 - INFO - Char 7/20: 7 (HTB{PN7.............)
2021-11-22 16:43:13,230 - INFO - Char 8/20: U (HTB{PN7U............)
2021-11-22 16:43:54,724 - INFO - Char 9/20: m (HTB{PN7Um...........)
2021-11-22 16:44:36,155 - INFO - Char 10/20: 4 (HTB{PN7Um4..........)
2021-11-22 16:45:17,593 - INFO - Char 11/20: t (HTB{PN7Um4t.........)
2021-11-22 16:45:59,053 - INFO - Char 12/20: 1 (HTB{PN7Um4t1........)
2021-11-22 16:46:40,088 - INFO - Char 13/20: C (HTB{PN7Um4t1C.......)
2021-11-22 16:47:20,785 - INFO - Char 14/20: _ (HTB{PN7Um4t1C_......)
2021-11-22 16:48:01,258 - INFO - Char 15/20: l (HTB{PN7Um4t1C_l.....)
2021-11-22 16:48:42,686 - INFO - Char 16/20: 0 (HTB{PN7Um4t1C_l0....)
2021-11-22 16:49:27,162 - INFO - Char 17/20: g (HTB{PN7Um4t1C_l0g...)
2021-11-22 16:50:10,463 - INFO - Char 18/20: 1 (HTB{PN7Um4t1C_l0g1..)
2021-11-22 16:50:53,553 - INFO - Char 19/20: C (HTB{PN7Um4t1C_l0g1C.)
2021-11-22 16:51:35,921 - INFO - Char 20/20: } (HTB{PN7Um4t1C_l0g1C})
2021-11-22 16:51:35,921 - INFO - First iteration flag: HTB{PN7Um4t1C_l0g1C}
2021-11-22 16:52:17,030 - INFO - Char 1/20: H (HTB{PN7Um4t1C_l0g1C})
2021-11-22 16:52:59,937 - INFO - Char 2/20: T (HTB{PN7Um4t1C_l0g1C})
2021-11-22 16:53:41,557 - INFO - Char 3/20: B (HTB{PN7Um4t1C_l0g1C})
2021-11-22 16:54:25,087 - INFO - Char 4/20: { (HTB{PN7Um4t1C_l0g1C})
2021-11-22 16:55:04,056 - INFO - Char 5/20: p (HTB{pN7Um4t1C_l0g1C})
2021-11-22 16:55:43,700 - INFO - Char 6/20: N (HTB{pN7Um4t1C_l0g1C})
2021-11-22 16:56:23,324 - INFO - Char 7/20: 3 (HTB{pN3Um4t1C_l0g1C})
2021-11-22 16:57:03,435 - INFO - Char 8/20: U (HTB{pN3Um4t1C_l0g1C})
2021-11-22 16:57:46,793 - INFO - Char 9/20: m (HTB{pN3Um4t1C_l0g1C})
2021-11-22 16:58:32,963 - INFO - Char 10/20: 4 (HTB{pN3Um4t1C_l0g1C})
2021-11-22 16:59:15,376 - INFO - Char 11/20: t (HTB{pN3Um4t1C_l0g1C})
2021-11-22 16:59:54,779 - INFO - Char 12/20: 1 (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:00:37,952 - INFO - Char 13/20: C (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:01:18,785 - INFO - Char 14/20: _ (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:01:59,601 - INFO - Char 15/20: l (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:02:39,105 - INFO - Char 16/20: 0 (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:03:18,524 - INFO - Char 17/20: g (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:03:57,573 - INFO - Char 18/20: 1 (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:04:36,417 - INFO - Char 19/20: C (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:05:17,208 - INFO - Char 20/20: } (HTB{pN3Um4t1C_l0g1C})
2021-11-22 17:05:17,208 - INFO - Second iteration flag: HTB{pN3Um4t1C_l0g1C}
2021-11-22 17:05:17,208 - INFO - Flag is: HTB{pN3Um4t1C_l0g1C}
109 changes: 109 additions & 0 deletions UniCTF_Quals_2021/Reverse/PneumaticValidator/solve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env python3

import numpy as np
import os
import string
import re
from functools import partial
from multiprocessing import Pool
import logging

# enable logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

'''
first loop -> HTB{PN7Um4t1C_l0g1C}
second loop -> HTB{pN3Um4t1C_l0g1C}
'''

BINARY = './pneumaticvalidator'

NB_PROCESSES = 10

FLAG_LENGTH = 0x14
POSSIBLE_CHARS = string.ascii_letters + string.digits + '_{}'

BREAKPOINT_ADDRESS = hex(0x555555559631)


# calculate fitness of char at index by using gdb-peda
# the aim is to set a breakpoint at the end of fitness calculation function
# then, run the program the partial flag, and read the RAX register in which is stored the fitness
def calculate_char_fitness(char: str, char_index: int, partial_flag: str) -> str:
# replace char at index in partial_flag
partial_flag = partial_flag[:char_index] + char + partial_flag[char_index + 1:]

# generate gdb command to set breakpoint and run program with partial flag
gdb_cmd = f'b *{BREAKPOINT_ADDRESS}\nr {partial_flag}'

# generate shell command to run gdb-peda with gdb command
cmd = f'echo "{gdb_cmd}" | gdb {BINARY} 2> /dev/null'

# run command in shell and get output
output = os.popen(cmd).read()

# get fitness stored in RAX register from output
m = re.search(r'RAX.+(0x[0-9a-f]+)', output)
fitness = int(m.group(1), 16)

# print fitness for debug
logging.debug(f'Fitness of {char}: {fitness} ({partial_flag})')

# return fitness
return fitness


# find char at index by bruteforce all possible chars and return the one with lowest fitness
def find_char(char_index: int, partial_flag: str) -> str:

# create a pool of processes to increase speed
with Pool(processes=NB_PROCESSES) as pool:

# create partial function with char_index and partial_flag
# because we need it to pass multiple arguments to the pool
f = partial(calculate_char_fitness, char_index=char_index, partial_flag=partial_flag)

# process function in parallel with pool.map
result = pool.map(f, POSSIBLE_CHARS)

# get char with lowest fitness
best_char_id = np.argmin(result)
best_char = POSSIBLE_CHARS[best_char_id]

# return most probable char
return best_char


def find_flag(flag: str) -> str:

for i in range(FLAG_LENGTH):
# get most probable char at index
char = find_char(i, flag)
# replace char in flag
flag = flag[:i] + char + flag[i + 1:]
# print partial flag
logging.info(f'Char {i + 1}/{FLAG_LENGTH}: {char} ({flag})')

# return most probable flag
return flag


def main():
# create flag template
flag = '.' * FLAG_LENGTH

# find flag from template
flag = find_flag(flag)
logging.info(f'First iteration flag: {flag}')

# reiterate with already found flag to confirm it and avoid false positives
flag = find_flag(flag)
logging.info(f'Second iteration flag: {flag}')

logging.info(f'Flag is: {flag}')


if __name__ == '__main__':
main()

0 comments on commit a1d79dc

Please sign in to comment.