Canary : ✓
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Partial
first, check the security options, PIE
isn’t enabled.
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
int int32; // eax
char s[32]; // [rsp+10h] [rbp-40h] BYREF
_QWORD v5[2]; // [rsp+30h] [rbp-20h] BYREF
__int64 v6; // [rsp+40h] [rbp-10h]
unsigned __int64 v7; // [rsp+48h] [rbp-8h]
v7 = __readfsqword(0x28u);
setup(argc, argv, envp);
memset(s, 0, 0x38uLL);
while ( 1 )
{
while ( 1 )
{
print_menu();
int32 = read_int32();
if ( int32 != 2 )
break;
printf("nationality: ");
__isoc99_scanf("%24s", v5);
}
if ( int32 > 2 )
{
if ( int32 == 3 )
{
printf("age: ");
__isoc99_scanf("%d", v6);
}
else if ( int32 == 4 )
{
if ( (unsigned __int8)auth(s) )
win();
}
else
{
LABEL_14:
puts("Invalid");
}
}
else
{
if ( int32 != 1 )
goto LABEL_14;
printf("name: ");
__isoc99_scanf("%32s", s);
}
}
}
in the main function, there are 4 menus.
change name, change nationality, change age, get shell.
if the return address of auth(s)
≠ 0, we can get the flag.
There are two ways to solve the problem.
The first one is to overflow nationality and edit the v6
so we can AAW
, printf@got → win
Another way is to find a correct string that is same as s2 after following encrypting
_BOOL8 __fastcall auth(__int64 a1)
{
signed int i; // [rsp+18h] [rbp-38h]
char s1[8]; // [rsp+20h] [rbp-30h] BYREF
__int64 v4; // [rsp+28h] [rbp-28h]
__int64 v5; // [rsp+30h] [rbp-20h]
__int64 v6; // [rsp+38h] [rbp-18h]
unsigned __int64 v7; // [rsp+48h] [rbp-8h]
v7 = __readfsqword(0x28u);
*s1 = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
for ( i = 0; i <= 0x1F; ++i )
s1[i] = ((*(a1 + i) >> 4) | (16 * *(a1 + i))) ^ *(main + i);
return strncmp(s1, &s2, 0x20uLL) == 0;
}
I think reversing is better.
this is simple encrypting, just swap 4 bit and xor with the main function opcode.
import sys
from pwn import *
with open("./challenge", "rb") as f:
data = f.read()
if sys.argv.__len__() == 4:
r = remote(sys.argv[1], int(sys.argv[3]))
else:
r = process("./challenge")
context.log_level = 'debug'
b = ELF("./challenge")
s2 = [0x11, 0xde, 0xcf, 0x10, 0xdf, 0x75, 0xbb, 0xa5, 0x43, 0x1e, 0x9d, 0xc2, 0xe3, 0xbf, 0xf5,
0xd6, 0x96, 0x7f, 0xbe, 0xb0, 0xbf, 0xb7, 0x96, 0x1d, 0xa8, 0xbb, 0xa, 0xd9, 0xbf, 0xc9, 0xd, 0xff]
main = data[0xB04:0xB04+0x20]
print(main)
print(s2[0] ^ main[0])
name = ''.join(list(map(lambda i: chr((
(s2[i] ^ main[i]) >> 4 | (s2[i] ^ main[i]) << 4) & 0xff), range(0x20))))
print(name)
r.send(b"1 ")
pause()
r.send(name[:0x20])
r.send(b"4 ")
r.interactive()
yeah