UTCTF 2024 On this page https://ctftime.org/event/2302
CHALL’S SOLVED# Beginner# Basic Reversing Problem# Overview Author: By Khael (@malfuncti0nal on discord)
Description: So many function calls… but are they that different?
baby-rev
In this basic reverse challenge we are given a binary file and after debugging it, there are many functions that we get afterwards
$ gdb ./baby-rev
gef➤ info functions
All defined functions:
Non-debugging symbols:
0x0000000000001000 _init
0x0000000000001040 __cxa_finalize@plt
0x0000000000001050 __stack_chk_fail@plt
0x0000000000001060 _start
0x0000000000001090 deregister_tm_clones
0x00000000000010c0 register_tm_clones
0x0000000000001100 __do_global_dtors_aux
0x0000000000001140 frame_dummy
0x0000000000001149 l1
0x0000000000001178 l2
0x00000000000011a7 l3
0x00000000000011d6 l4
0x0000000000001205 l5
0x0000000000001234 l6
0x0000000000001263 l7
0x0000000000001292 l8
0x00000000000012c1 l9
0x00000000000012f0 l10
0x000000000000131f l11
0x000000000000134e l12
0x000000000000137d l13
0x00000000000013ac l14
0x00000000000013db l15
0x000000000000140a l16
0x0000000000001439 l17
0x0000000000001468 l18
0x0000000000001497 l19
0x00000000000014ad keygen
0x00000000000014eb main
0x0000000000001510 __libc_csu_init
0x0000000000001580 __libc_csu_fini
0x0000000000001588 _fini
We can use Ghidra/IDA to see the decompiled version
void l1 ( undefined * param_1 )
{
* param_1 = 0x75 ;
l2 ( param_1 + 1 );
return ;
}
void l2 ( undefined * param_1 )
{
* param_1 = 0x74 ;
l3 ( param_1 + 1 );
return ;
}
void l3 ( undefined * param_1 )
{
* param_1 = 0x66 ;
l4 ( param_1 + 1 );
return ;
}
...
void l18 ( undefined * param_1 )
{
* param_1 = 0x7d ;
l19 ( param_1 + 1 );
return ;
}
So.. if we decode hex value of l1
… l18
functions one by one we can get the part of flag
$ python3
>>> bytes.fromhex( '75 74 66 6c 61 67' ) .decode( 'utf-8' )
'utflag'
>>>
Final solver
>>> vals = [ 0x75, 0x74, 0x66, 0x6c, 0x61, 0x67, 0x7b, 0x69, 0x5f, 99, 0x34, 0x6e, 0x5f, 0x72, 0x33, 0x76, 0x21
, 0x7d]
>>>
>>> print( '' .join( chr( value) for value in vals))
utflag{ i_c4n_r3v!}
FLAG utflag{i_c4n_r3v!}
Off-Brand Cookie Clicker# Overview Author: By Khael (@malfuncti0nal on discord)
Description: I tried to make my own version of cookie clicker, without all of the extra fluff. Can you beat my highscore?
http://betta.utctf.live:8138/
From the provided link, we have to exceed 10,000,000 clicks.
It displays this count on an HTML element with the id clickCount
. An event listener is added to an HTML element with the id cookieImage
.
When this element is clicked, the count is incremented & the new count is displayed and stored in the local storage. If the count reaches or exceeds 10,000,000
, a POST request is sent to the /click
endpoint with the count as the body of the request.
1 import requests
2
3 url = "http://betta.utctf.live:8138/click"
4
5 headers = {
6 'Content-Type' : 'application/x-www-form-urlencoded'
7 }
8
9 data = {
10 'count' : 10000000
11 }
12
13 response = requests . post ( url , headers = headers , data = data )
14
15 print ( response . json ())
$ python3 solve.py
{ 'flag' : 'Wow, you beat me. Congrats! utflag{y0u_cl1ck_pr3tty_f4st}' }
FLAG utflag{y0u_cl1ck_pr3tty_f4st}
Cryptography# RSA-256# Overview Author: By Jeriah (@jyu on discord)
Description: Based on the military-grade encryption offered by AES-256, RSA-256 will usher in a new era of cutting-edge security… or at least, better security than RSA-128.
vals.txt
From the given source. The values are:
N: the modulus for both the public and private keys e: the public exponent c: the ciphertext want to decrypt N = 77483692467084448965814418730866278616923517800664484047176015901835675610073
e = 65537
c = 43711206624343807006656378470987868686365943634542525258065694164173101323321
To solve this, we would factorize N
into two prime numbers, p
and q
. This is often the most time-consuming step, especially when N
is a large number. Alternatively, we can use online factorization tools such as FactorDB . Just enter the number and it will return the factors.
After we get the factors of N
. Here’s the optional step that might check whether p
and q
are indeed factors of N
.
N = 77483692467084448965814418730866278616923517800664484047176015901835675610073
p = 1025252665848145091840062845209085931
q = 75575216771551332467177108987001026743883
if p * q == N :
print ( "p * q == N" )
else :
print ( "p * q != N" )
Final solver
1 from Crypto.Util.number import inverse , long_to_bytes
2
3 # given values
4 N = 77483692467084448965814418730866278616923517800664484047176015901835675610073
5 e = 65537
6 c = 43711206624343807006656378470987868686365943634542525258065694164173101323321
7
8 # factorized (N) with factordb.com
9 p = 1025252665848145091840062845209085931
10 q = 75575216771551332467177108987001026743883
11
12 phi = ( p - 1 ) * ( q - 1 )
13 d = inverse ( e , phi )
14 m = pow ( c , d , N )
15
16 message = long_to_bytes ( m )
17 print ( message )
$ python3 solve.py
b'utflag{just_send_plaintext}'
FLAG utflag{just_send_plaintext}
Forensics# Contracts# Overview Author: By Samintell (@samintell on discord)
Description: Magical contracts are hard. Occasionally, you sign with the flag instead of your name. It happens.
document.pdf
Given the forensics challenge, and provided PDF document
Trying various ways to search flags, such as searching for all uppercase letters, but it didn’t work
$ pdftotext file.pdf output.txt
$ grep -o '[A-Z]' output.txt
So, after searching for PDF forensics tools, we found a tool that was suitable for solving this by extracting images from PDF using pdfimages
$ mkdir ext && pdfimages -all document.pdf out && mv out* ext
$ ls ext/
out-000.jpg out-002.jpg out-004.png out-006.png out-008.png
out-001.jpg out-003.png out-005.png out-007.png
We got several extracted image, and one of them there was an image that contained a flag
FLAG utctf{s1mple_w1z4rding_mist4k3s}