zer0pts CTF
main
__int64 __fastcall main(int a1, char **a2, char **a3)
{
if ( a1 == 2 )
puts(a2[1]);
else
puts("Feed me flag");
return 0LL;
}
unsigned __int64 sub_932()
{
__int64 v0; // rax
int status; // [rsp+8h] [rbp-178h]
unsigned int cpid; // [rsp+Ch] [rbp-174h]
char v4[144]; // [rsp+10h] [rbp-170h]
_QWORD regs[27]; // [rsp+A0h] [rbp-E0h]
unsigned __int64 v6; // [rsp+178h] [rbp-8h]
v6 = __readfsqword(0x28u);
cpid = syscall(57LL); // fork
if ( cpid )
{
// parent
syscall(61LL, cpid, &status, 0LL, v4); // waitpid(pid, status, 0)
syscall(101LL, 16896LL, cpid, 0LL, 1LL); // ptrace(SETOPTIONS, cpid, 0, TRACESYSGOOD)
while ( 1 )
{
syscall(101LL, 24LL, cpid, 0LL, 0LL); // ptrace(SYSCALL, cpid, 0, 0) (continue child but break next syscall
syscall(61LL, cpid, &status, 0LL, v4); // waitpid(cpid, status, 0)
if ( (unsigned __int8)status == 127 && status & 0x8000 )// // WSTOPPED(status)
{
syscall(101LL, 12LL, cpid, 0LL, regs); // ptrace(GETREGS, cpid, 0, regs)
sub_7E1(cpid, regs);
}
if ( !(status & 0x7F) )
syscall(231LL, 0LL); // sys_exit_group
}
}
// child
syscall(101LL, 0LL, 0LL, 0LL, 0LL); // ptrace(TRACEME)
//
v0 = syscall(39LL); // getpid
syscall(62LL, v0, 19LL); // kill(pid, SIGSTOP)
return __readfsqword(0x28u) ^ v6;
}
sub_932
do
PTRACE_TRACEME
and break every syscallsub_7E1
__int64 __fastcall sub_7E1(unsigned int cpid, _QWORD *regs)
{
unsigned __int64 v2; // rax
char __rsi; // [rsp+1Fh] [rbp-1h]
v2 = regs[15]; // orig_rax?
if ( v2 == 5 ) // sys_fstat
{
dword_202158 = 0;
}
else if ( v2 > 5 )
{
if ( v2 == 12 ) // sys_brk
{
dword_202154 = 0;
}
else if ( v2 == 231 ) // exit_group
{
if ( dword_202158 )
puts("Wrong!");
else
puts("Correct!");
}
}
else if ( v2 == 1 ) // write
{
__rsi = ptrace(PTRACE_PEEKDATA, cpid, regs[13], 0LL);// read RSI
regs[12] = 1LL; // rdi
dword_202158 |= sub_75A(__rsi, 23531LL, 2343464867LL) - dword_202020[2 * (int)*(float *)&dword_202154];
*(float *)&dword_202154 = *(float *)&dword_202154 + 0.5;
}
return syscall(101LL, 13LL, cpid, 0LL, regs); // ptrace(SETREGS, cpid, 0, regs)
}
v2
stores syscall number. if child calls write
, use PTRACE_PEEKDATA
to get the RSI
of children (this may the output character), and check sub_75A(__rsi, 23531LL, 2343464867LL)
equals to dword_202020[counter]
.
sub_75A
is obviously powmod
. so this check may use RSA
. This means RSA dcryption is to get the correct input.
from Crypto.Util.number import *
p, q = 42821, 54727
n = p * q
phi = (p-1)*(q-1)
e = 23531
d = inverse(e, phi)
arr = [0x1A400138, 0x279AB867, 0x177D2969, 0x0E6E46F5,
0x512621F8, 0x2E96CE73, 0x484B496, 0x73414F6E,
0x484B496, 0x1C274E9, 0x484B496, 0x637DC762,
0x15147A4A, 0x1FE9895E, 0x1FE9895E, 0x862B01EB,
0x775A06CD, 0x0E6E46F5, 0x0E6E46F5, 0x3E6A2466,
0x300AB6D, 0x5A67CC12, 0x34167E01, 0x862B01EB,
0x300AB6D, 0x484B496, 0x862B01EB, 0x300AB6D,
0x11EFDA4D, 0x512621F8, 0x0E6E46F5, 0x177D2969,
0x2E96CE73, 0x15147A4A, 0x5A67CC12, 0x2E96CE73,
0x7880144D, 0x5A69ED6B]
ms = []
for x in arr:
ms.append(chr(pow(x, d, n)))
print("".join(ms))
zer0pts{sysc4ll_h00k1ng_1s_1mp0rt4nt}
good chal.