Messy Malloc
We can get the flag using print-flag
command. Before the print_flag
function actualy print the flag, it needs to validate access information.
unsigned long ac1 = ((unsigned long *)u->access_code)[0];
unsigned long ac2 = ((unsigned long *)u->access_code)[1];
if (ac1 != 0x4343415f544f4f52 || ac2 != 0x45444f435f535345) {
fprintf(stdout, "Incorrect Access Code: \"");
for (int i = 0; i < ACCESS_CODE_LEN; i++) {
putchar(u->access_code[i]);
}
fprintf(stdout, "\"\n");
return;
}
>>> pwn.p64(0x4343415f544f4f52)
b'ROOT_ACC'
>>> pwn.p64(0x45444f435f535345)
b'ESS_CODE'
Which means the access_code
needs to be ROOT_ACCESS_CODE
.
So how do we set the correct code to access_code
?
Take a look at login
, it’s using malloc
to allocate memory for user struct and username, as malloc
simply allocate chunks of memory without initialization, information previously written there will still exists.
In logout
, the user struct is being freed first, and then, the username. The deallocated pointers are stored like a stack, when it needs to allocate again, as in login
, the old pointer to username is being used to create user struct.
| username |
| user struct |
| ----------- |
Now, we need to store the user
struct in username, so that the access_code
can be the expected one.
>>> len('A'*8+'ROOT_ACCESS_CODE'+'A'*8)
32
Login with username 'A'*8+'ROOT_ACCESS_CODE'+'A'*8
, logout, and then, login again with a shorter name to get flag with command print_flag
.