#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
char *getpath()
{
char buffer[64];
unsigned int ret;
printf("input path please: "); fflush(stdout);
gets(buffer);
ret = __builtin_return_address(0);
if((ret & 0xb0000000) == 0xb0000000) {
printf("bzzzt (%p)
", ret);
_exit(1);
}
printf("got path %s
", buffer);
return strdup(buffer);
}
int main(int argc, char **argv)
{
getpath();
}
stack6 문제에서 if 문이 달라졌다.
[그림 1-1] 은 stack6번 exploit 이다. ret 값에 system_addr 값이 들어가는데 if문에서 0xb0000000 과 and 연산 결과가 0xb0000000 나오면 안된다.
system_addr 과 and 연산에 결과가 0xb0000000 이다. 따라서 RTL 방법은 사용할 수 없다.
shellcode 를 넣고 shellcode 위치를 직접 가리킬 수 없고 시스템 주소도 넣을 수 없다, 따라서 stack7 문제는 ROP 로 해결해 보자.
[그림 1-3] 참조하면 [그림 1-4] 그릴 수 있다.
ROP 기법을 사용한다. 따라서 payload는 "A" * 80 + ret 명령어 주소 + system 함수 주소 + dummy + /bin/sh 이다.
ret 명령어 주소는 [그림 1-5] 처럼 쉽게 구할 수 있다.
성공!
rop 주소는 gdb 에서 프로그램 실행 후 ropgadget 명령어로 구할 수 있다.
[그림 2-1] 확인하면 popret, pop2ret .. 확인할 수 있는데 말그대로 pop 명령어 수행 후 ret 수행한다는 뜻이다. 숫자는 pop 횟수이다. pop을 하는 이유는 스택에서 system 함수를 넣는 위치가 프로그램 실행되면서 다른 값으로 변조되면 엉뚱한 곳으로 eip가 실행되기 때문에 변조되는 부분은 pop으로 스택에서 빼기위함이다.
ROP 와 비슷한 jmpcall esp 방법으로 stack7 풀 수 있다.
jmpcall esp libc 입력하면 jmp, call 명령어를 사용하는 주소가 뜬다. 따라서 payload를 "A" * 80 + jmp rsp 명령어 주소 + shellcode 입력하면 된다.
하지만 주소를 확인하면 0x7fff.. 이므로 if문에서 걸린다. 원래는 다른 주소도 떠야하는데 컴파일러 마다 차이가 있어 뜨지않아 결국 ROP로 풀어야한다. 째든 원리는 이해하자!
'protostar' 카테고리의 다른 글
format2 (0) | 2023.01.24 |
---|---|
format0 (0) | 2023.01.24 |
stack6 (0) | 2022.09.09 |
stack5 - Return to libc(RTL) (0) | 2022.09.07 |
stack5 - 쉘 코드 (0) | 2022.09.07 |