일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 홍대 카페 장쌤
- promise메서드
- 운정 소바동
- 화이트해커를 위한 웹 해킹의 기술
- graphql 400
- graphql with RN
- typescript
- useMutation error
- graphql
- apolloclient
- graphql with reactnative
- 잠실새내 도그존
- 신촌 소문난집
- 잠실새내
- 도그존
- 금별맥주
- 비동기배열처리방법
- 홍대 예술
- apollo react native
- graphql react native
- graphql mutation error
- 앙버터마카롱
- 고르드
- 지보싶 신촌점
- 예쁜술집 예술
- 비동기배열
- 홍대 토라비
- 토라비
- promise처리
- 화이트 해커를 위한 웹 해킹의 기술
- Today
- Total
yehey's 공부 노트 \n ο(=•ω<=)ρ⌒☆
LOB 7번 풀이 (darkelf) 본문
id: darkelf
pw: kernel crashed
/*
The Lord of the BOF : The Fellowship of the BOF
- orge
- check argv[0]
*/
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
main(int argc, char *argv[])
{
char buffer[40];
int i;
if(argc < 2){
printf("argv error\n");
exit(0);
}
// here is changed!
if(strlen(argv[0]) != 77){
printf("argv[0] error\n");
exit(0);
}
// egghunter
for(i=0; environ[i]; i++)
memset(environ[i], 0, strlen(environ[i]));
if(argv[1][47] != '\xbf')
{
printf("stack is still your friend.\n");
exit(0);
}
// check the length of argument
if(strlen(argv[1]) > 48){
printf("argument is too long!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
// buffer hunter
memset(buffer, 0, 40);
}
- strcpy의 BOF 취약점 이용해서 공격
- egghunter 코드 삽입 (환경변수를 이용한 공격 불가능)
- bufferhunter 코드 삽입 (buffer 내에 쉘코드 삽입해도 0으로 초기화 됨, 사용 불가)
- 전달하려는 문자열의 48번째는 "\xbf"와 같아야함 (같지 않으면 강제종료)
- buffer에 담긴 내용 출력
- argv[1]에 전달되는 문자열 길이가 48보다 길어서는 안됨
- argv[0]의 strlen이 77이어야 함 (argv[0]은 실행파일 명)
orge 디스어셈블
스택 구조는 이전 문제들과 같으므로 생략
이번에도 buffer를 초기화하기 때문에 쉘 코드를 저장할 다른 공간을 찾아주어야 한다.
wolfman에서는 argv[2]를 사용했으나, 이번에는 exploit 코드로 전달이 잘 되지 않아서 다른 방법을 찾아야 했다.
그래서 일단 orge gdb에서 main에 breakpoint를 걸고 argv[1]에 인자로 "\x90"을 48바이트 전달해보았다.
그리고 esp를 확인해보았더니 buffer로 추정되는 부분은 0으로 초기화 되어있었고 (0xbffffbf9 부터 40바이트)
더 아래를 보면 "\x90"이 48바이트 만큼 (내가 입력한 만큼) 특정 공간에 남아있었다.
즉, buffer는 초기화해도 argv[1]은 초기화 되지 않고 남아있다.
따라서 이전처럼 argv[1]에 NOP와 쉘 코드를 넣어 전달해주고 ret 주소에는 buffer 시작주소가 아닌 argv[1]의 주소를 넣어주자.
그러면 argv[1]의 주소를 알아내기 위해 orge.c를 복사해서 코드를 살짝 수정한 후 컴파일해서 실행해보자
/*
orge2의 code
*/
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
main(int argc, char *argv[])
{
char buffer[40];
int i;
if(argc < 2){
printf("argv error\n");
exit(0);
}
printf("argv[1] addr: %x\n",argv[1]); //argv[0] 체크 전에 argv[1]의 주소 출력
// here is changed!
if(strlen(argv[0]) != 77){
printf("argv[0] error\n");
exit(0);
}
// egghunter
for(i=0; environ[i]; i++)
memset(environ[i], 0, strlen(environ[i]));
if(argv[1][47] != '\xbf')
{
printf("stack is still your friend.\n");
exit(0);
}
// check the length of argument
if(strlen(argv[1]) > 48){
printf("argument is too long!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%x\n", buffer);
// buffer hunter
memset(buffer, 0, 40);
}
실행할 때는 exploit 코드와 최대한 동일하게 작성하는 것이 좋다. 전달하는 argv[1]가 달라지면 주소도 달라질 수 있기 때문이다.
앞서 코드를 분석했을 때 argv[0] 즉, 실행파일 명이 77이어야 정상적으로 실행되기 때문에 실행파일명의 길이를 77바이트로 늘려주어야한다. "/"는 여러개를 사용해도 1개로 인식하기 때문에 "/"을 이용해 77을 맞춰주자.
실행한 결과 0xbffff9e0이 argv[1]의 주소이다.
따라서 orge에 NOP와 쉘 코드를 전달해주고 ret에는 argv[1]의 주소인 0xbffff9e0을 넣어주자
orge 권한으로 bash 쉘이 실행되었다.
orge의 pw: "timewalker"
'wargame 풀이 > LOB' 카테고리의 다른 글
LOB 9번 풀이 (troll) (0) | 2020.11.21 |
---|---|
LOB 8번 풀이 (orge) (0) | 2020.11.19 |
LOB 6번 풀이 (wolfman) (0) | 2020.11.07 |
LOB 5번 풀이 (orc) (0) | 2020.11.06 |
LOB 4번 풀이 (goblin) (0) | 2020.11.02 |