
system, execve) 자동 검색Binwalk 활용)Firmwalker)Nuclei)Ghidra 또는 Radare2)1단계:
nuclei -t http -target /path/to/extracted/firmware/(정적 분석)
2단계: 펌웨어를 QEMU로 실행 후nuclei -t http -u http://192.168.1.1(동적 분석)
cd firmwalker
./firmwalker.sh ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio_root
┌──(lee㉿kali)-[~/Desktop/firmwalker]
└─$ ./firmwalker.sh /home/lee/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root
***Firmware Directory***
/home/lee/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root
***Search for password files***
##################################### passwd
##################################### shadow
##################################### *.psk
***Search for Unix-MD5 hashes***
***Search for SSL related files***
##################################### *.crt
##################################### *.pem
t/etc_ro/public.pem
Could not find certificate from /home/lee/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/etc_ro/public.pem
40F70198207F0000:error:1608010C:STORE routines:ossl_store_handle_load_result:unsupported:../crypto/store/store_result.c:151:
Incorrect File Content:Continuing
Error: Please run "shodan init <api key>" before using this command
비밀번호 관련 정보(passwd, shadow, .psk) 탐지 실패
/etc/passwd, /etc/shadow 같은 파일에서 사용자 계정 정보가 발견되지 않음SSL 관련 파일 탐지 (public.pem)
etc_ro/public.pem 파일이 탐지되었지만, 오류가 발생Shodan API 키 관련 경고
┌──(lee㉿kali)-[~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/etc_ro]
└─$ cat public.pem
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEApZLuH2XFDWuazEMpx4v6QY0ePRJm344JgkLKfeofovxvbjfX6RHU
7yUz6b2wJnW4lomEzjrJEQFnPGNFV/oWO/NaTb3k0rPUewDzlzy/pn7ZMehqnMK1
tHVnyQ6RZ+9qkdYEu08f79UgZcGQzSy2TLNMquAB9ffGbTHAjRfoK7cDjQX+RKWh
OOs5tbnzhR0B4Jdd6UL9Sqoq5UisTdlnFhy67RdsItz3OOrHIiDYmfkEOqAZySKZ
MhY7h7kkC8t1IzZOncBx3LYU4PMo9ulycAx7xDUric8xswnKoYAJbbKtp9xnGKRJ
HPuZOZyXFdWNlTVhzG3sGdDzcpHxrFOJZ5RK/n19DArbq6w9MEInTmU3bcwDYFvX
JCQ5Al05lgqP8vk7U4xx3AcwZUQHNVzduBuibB26jhpPXSk1Cl6NpFdXlKvcynfV
H8XaCHy8LXhZBMiuR62Ft6YkcIpBdsQ2uBGL5GOmVFA/cOEtPZjWxzN/miXaZ7In
iRhXEHFus6zYIPOTa9DNyAA87UCqxkem7Xgu59fgq49YwGPk+Q7HJXKgts9QTn9y
26OtlUAq1i23EJK6GJvTmszslXbAWEi5Mlb/o7QdpEQt/gyz9udnVmfXOy4UmNXN
ZxuVyXNomTBFRObZ5Zmn6n+xat5eBDpvct+OO1IUMC154div9i2szF0CAwEAAQ==
-----END RSA PUBLIC KEY-----
┌──(lee㉿kali)-[~/Desktop]
└─$ grep -R "public.pem" ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/
grep: /home/lee/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/bin/imgdecrypt: binary file matches
public.pem이 imgdecrypt 바이너리에서 참조됨imgdecrypt가 RSA 공개 키를 사용해 파일(펌웨어 이미지 등)을 복호화하는 기능을 포함하고 있을 가능성┌──(lee㉿kali)-[~/Desktop]
└─$ file ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/bin/imgdecrypt
/home/lee/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/bin/imgdecrypt: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
┌──(lee㉿kali)-[~/Desktop]
└─$ strings ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/bin/imgdecrypt | grep -i "public.pem"
/etc_ro/public.pem
┌──(lee㉿kali)-[~/Desktop]
└─$ ldd ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/bin/imgdecrypt
not a dynamic executable
파일 타입 (file 명령어 결과)
- MIPS 32-bit Little Endian ELF 실행 파일
- 동적으로 링크됨 (dynamically linked)
- Stripped (디버깅 심볼 제거됨)
- uClibc 사용 (/lib/ld-uClibc.so.0)
파일 내부 문자열 (strings 분석 결과)
- /etc_ro/public.pem을 직접 참조하고 있음 → RSA 공개 키를 이용한 암호화/복호화 기능 포함 가능성
라이브러리 의존성 (ldd 결과)
- "not a dynamic executable" 오류 발생
- 보통 statically linked (정적으로 링크됨) 실행 파일일 경우 나타남
- 즉, 라이브러리가 바이너리에 직접 포함되어 있으며, ldd로 의존성을 확인할 수 없음
sudo apt install nuclei -y
┌──(lee㉿kali)-[~/Desktop]
└─$ nuclei -version
[INF] Nuclei Engine Version: v3.3.8
[INF] Nuclei Config Directory: /home/lee/.config/nuclei
[INF] Nuclei Cache Directory: /home/lee/.cache/nuclei
[INF] PDCP Directory: /home/lee/.pdcp
┌──(lee㉿kali)-[~/Desktop]
└─$ nuclei -ut
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.3.8
projectdiscovery.io
[INF] nuclei-templates are not installed, installing...
[INF] Successfully installed nuclei-templates at /home/lee/.local/nuclei-templates
[INF] No new updates found for nuclei templates
┌──(lee㉿kali)-[~/Desktop]
└─$ nuclei -t http -target ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/etc_ro/lighttpd/www/web/
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.3.8
projectdiscovery.io
[WRN] Found 2 templates with runtime error (use -validate flag for further examination)
[INF] Current nuclei version: v3.3.8 (latest)
[INF] Current nuclei-templates version: v10.1.2 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 52
[INF] Templates loaded for current scan: 7397
[INF] Executing 7020 signed templates from projectdiscovery/nuclei-templates
[WRN] Loading 377 unsigned templates for scan. Use with caution.
[INF] Targets loaded for current scan: 1
[INF] Running httpx on input host
[INF] Found 0 URL from httpx
[INF] Templates clustered: 1647 (Reduced 1550 Requests)
[INF] Using Interactsh Server: oast.live
[INF] No results found. Better luck next time!
-validate 태그 붙여줌┌──(lee㉿kali)-[~/Desktop]
└─$ nuclei -t http -target ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/etc_ro/lighttpd/www/web/ -validate
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.3.8
projectdiscovery.io
[url] got empty hostname for /home/lee/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/etc_ro/lighttpd/www/web/ skipping ip selection
[VER] Started metrics server at localhost:9092
[ERR] Error occurred parsing template /home/lee/.local/nuclei-templates/http/technologies/wordpress/plugins/userfeedback-lite.yaml: could not compile request: could not parse payloads: the helpers/wordpress/plugins/userfeedback-lite.txt file for payload last_version does not exist or does not contain enough elements
[WRN] Found duplicate template ID during validation '/home/lee/.local/nuclei-templates/http/exposures/configs/javascript-env.yaml' => '/home/lee/.local/nuclei-templates/http/exposures/files/javascript-env.yaml': javascript-env
[ERR] Error occurred parsing template /home/lee/.local/nuclei-templates/http/technologies/wordpress/plugins/jeg-elementor-kit.yaml: could not compile request: could not parse payloads: the helpers/wordpress/plugins/jeg-elementor-kit.txt file for payload last_version does not exist or does not contain enough elements
[FTL] Could not validate templates: errors occurred during template validation
/www/web/ 디렉토리는 로컬 파일 시스템이므로, Nuclei가 이를 대상으로 제대로 작동할 수 없음http://TARGET_IP/을 대상으로 스캔해야 함┌──(lee㉿kali)-[~/Desktop]
└─$ nuclei -t http/hnap -target ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/etc_ro/lighttpd/www/web/hnap/
__ _
____ __ _______/ /__ (_)
/ __ \/ / / / ___/ / _ \/ /
/ / / / /_/ / /__/ / __/ /
/_/ /_/\__,_/\___/_/\___/_/ v3.3.8
projectdiscovery.io
[ERR] Could not find template 'http/hnap': could not find file: open /home/lee/.local/nuclei-templates/http/hnap: no such file or directory
[INF] Current nuclei version: v3.3.8 (latest)
[INF] Current nuclei-templates version: v10.1.2 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] Targets loaded for current scan: 1
[INF] No results found. Better luck next time!
[FTL] Could not run nuclei: no templates provided for scan
┌──(lee㉿kali)-[~/Desktop]
└─$ file ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/sbin/fwupload.cgi
/home/lee/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/sbin/fwupload.cgi: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped
/lib/ld-uClibc.so.0)┌──(lee㉿kali)-[~/Desktop]
└─$ strings ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/sbin/fwupload.cgi | less
/lib/ld-uClibc.so.0
_init
_fini
__uClibc_main
__deregister_frame_info
__register_frame_info
_Jv_RegisterClasses
memchr
memcmp
memset
FCGI_fopen
malloc
FCGI_fseek
FCGI_ftell
FCGI_fread
ntohl
nvram_safe_get
strcmp
crc32
FCGI_fclose
free
FCGI_printf
FCGI_perror
lseek
snprintf
__errno_location
ftruncate
strlen
FCGI_fwrite
system
getenv
strstr
exit
libnvram.so.0
_DYNAMIC_LINKING
__RLD_MAP
_GLOBAL_OFFSET_TABLE_
libc.so.0
memmem
libfcgi.so.0
libjson-c.so.2
libm.so.0
libcrypto.so.1.0.0
libnotifyrc.so
librcm.so
libssl.so.1.0.0
_ftext
_fdata
_edata
__bss_start
_fbss
_end
#9'g
's&#
$! `
%E$x
B$!
%D$0
$! `
%D$t
%B$$
'! `
$!0@
'! @
$! `
$! `
&D$@
<(&E$x
<,&D$
$!0@
&D$@
<(&E$x
<,&D$
$!0@
&D$@
<(&E$x
<,&D$
<0&B$0
$!0@
&D$@
<(&E$x
'! @
'! `
$!0@
$! `
$! `
%D$t
<H&D$t
<X&B$H
'! `
$!0@
'! @
<d&B$H
'! `
$!0@
'! @
$! `
<x&D$t
&B$H
'! `
$!0@
'! @
'! `
&D$t
&P$8
'! @
&P$8
'! @
&P$8
'! @
&B$H
$!0@
'! @
$! `
'B$$
'! `
$!0@
'! @
'P$@
<('D$
'! `
'! @
<8'D$
<H'E$P
<T'D$!(
<t'C$A
$!0`
'! @
'D$!(
'D$!(
SHRS
model_name
Usage %s file_name offset : %d,length : %d
open
ftruncate_file,filename:%s
/dev/console
fail :%s , status :%d
read head tail
offset:%d
endoffset end:%d
remove read head tail
n :%d
error end boundary
len:%d,%p,%s
endoffset:%d - offset:%d = %d,strlen(p)=%d
error:%d,%s
UPLOAD_FILENAME
filename:%s
SERVER_SOFTWARE:%s
SERVER_SOFTWARE
CONTENT_TYPE
boundary=
failed, can't find boundary=.
boundary:%s
failed, can't remove head tail.
check fw header FAILED
.shstrtab
.interp
.reginfo
.dynamic
.hash
.dynsym
.dynstr
.init
.text
.MIPS.stubs
.fini
.rodata
.eh_frame
.ctors
.dtors
.jcr
.data
.rld_map
.got
.sdata
.bss
.pdr
.gnu.attributes
.mdebug.abi32
system() 함수를 호출system() 함수가 포함되어 있음 → 명령어 실행 취약점(RCE, Command Injection) 가능성 있음system()을 호출하는 경우, 임의 명령 실행 가능FCGI_* 관련 함수 발견 → FastCGI 기반 웹 서비스FCGI_fopen, FCGI_fseek, FCGI_ftell, FCGI_fread, FCGI_printf, FCGI_fwrite 등 FastCGI 관련 함수 다수 발견nvram_safe_get() 함수 발견 → NVRAM 설정 접근 가능성nvram_safe_get)가 포함"UPLOAD_FILENAME" / "filename=%s" 문자열 발견 → 파일 업로드 기능 포함"check fw header FAILED" 메시지 → 업로드된 펌웨어 파일의 헤더 검증을 수행하는 것으로 보임"boundary=" 관련 문자열 발견 → Multipart Form Data 처리"failed, can't find boundary=.", "boundary:%s" 등의 문자열이 포함됨multipart/form-data)을 통해 파일 업로드를 수행할 수 있음"fail :%s , status :%d", "error end boundary" → 오류 메시지 포함r2 사용)┌──(lee㉿kali)-[~/Desktop]
└─$ r2 -AA ~/Desktop/Firmware/inspection_result/_DIR882A1_FW104B02_Middle_FW_Unencrypt.bin.extracted/_A0.extracted/_8AB758.extracted/cpio-root/sbin/fwupload.cgi
WARN: Relocs has not been applied. Please use `-e bin.relocs.apply=true` or `-e bin.cache=true` next time
INFO: Analyze all flags starting with sym. and entry0 (aa)
INFO: Analyze imports (af@@@i)
INFO: Analyze entrypoint (af@ entry0)
INFO: Analyze symbols (af@@@s)
INFO: Recovering variables
INFO: Analyze all functions arguments/locals (afva@@@F)
INFO: Analyze function calls (aac)
INFO: Analyze len bytes of instructions for references (aar)
INFO: Finding and parsing C++ vtables (avrr)
INFO: Analyzing methods
INFO: Finding xrefs in noncode section (e anal.in=io.maps.x)
INFO: Emulate functions to find computed references (aaef)
INFO: Recovering local variables (afva)
INFO: Type matching analysis for all functions (aaft)
INFO: Propagate noreturn information (aanr)
INFO: Scanning for strings constructed in code (/azs)
INFO: Finding function preludes (aap)
INFO: Enable anal.types.constraint for experimental type propagation
[0x00400980]>
[0x00400980]> afl
0x00402530 1 32 sym.imp.ntohl
0x004009e0 8 204 fcn.004009e0
0x00402520 1 16 sym.imp.FCGI_fwrite
0x00402510 1 16 sym.imp.free
0x00402500 1 16 sym.imp.FCGI_fclose
0x004024f0 1 16 sym.imp.FCGI_printf
0x004024e0 1 16 sym.imp.FCGI_ftell
0x004024d0 1 16 sym.imp.strcmp
0x004024c0 1 16 sym.imp.strstr
0x004024b0 1 16 sym.imp.exit
0x004024a0 1 16 sym.imp.memchr
0x00402490 1 16 sym.imp.FCGI_fseek
0x00402480 1 16 sym.imp.memcmp
0x00402470 1 16 sym.imp.ftruncate
0x00402460 1 16 sym.imp.memset
0x00402450 1 16 sym.imp.close
0x00402440 1 16 sym.imp.write
0x00402430 1 16 sym.imp.FCGI_perror
0x00402420 1 16 sym.imp.FCGI_fopen
0x00402410 1 16 sym.imp.crc32
0x00402400 1 16 sym.imp.nvram_safe_get
0x004023f0 1 16 sym.imp.read
0x004023e0 1 16 sym.imp.snprintf
0x004023d0 1 16 sym.imp.lseek
0x004023c0 1 16 sym.imp.strlen
0x004023b0 1 16 sym.imp.FCGI_fread
0x004023a0 1 16 sym.imp.__uClibc_main
0x00402390 1 16 sym.imp.malloc
0x00402380 1 16 sym.imp.system
0x00402370 1 16 sym.imp.getenv
0x00402360 1 16 sym.imp.open
0x00402350 1 16 sym.imp.__errno_location
0x00400980 2 88 entry0
0x00402550 1 84 sym._fini
0x00400b30 10 348 sym.memmem
0x00402030 9 720 main
0x004008fc 1 120 sym._init
0x00400aac 6 120 fcn.00400aac
0x00402300 4 76 fcn.00402300
0x00401528 9 780 fcn.00401528
0x00401434 9 244 fcn.00401434
0x004010b8 18 892 fcn.004010b8
0x00401834 28 2044 fcn.00401834
0x00400c8c 20 1068 fcn.00400c8c
fwupload.cgi 실행 파일이 파일 업로드를 처리하고 system() 함수를 호출하는 것이 확인system() 호출이 어디서 이루어지는지 확인, 이후 심층 분석 진행system() 함수를 호출하는 코드 확인[0x00400980]> afl | grep system
0x00402380 1 16 sym.imp.system
main 함수 분석[0x00400980]> pdf @ main
; NULL XREF from section..dynsym @ +0xd4(r)
; ICOD XREF from entry0 @ 0x400998(r)
┌ 720: int main (int argc, char **argv, int32_t envp, int32_t arg_134h);
│ ; arg int argc @ a0
│ ; arg char **argv @ a1
│ ; arg int32_t envp @ sp+0x158
│ ; arg int32_t arg_134h @ sp+0x15c
│ ; var int32_t var_10h @ sp+0x38
│ ; var int32_t var_18h @ sp+0x40
│ ; var int32_t var_1ch @ sp+0x44
│ ; var int32_t var_20h @ sp+0x48
│ ; var int32_t var_24h @ sp+0x4c
│ ; var int32_t var_128h @ sp+0x150
│ ; var int32_t var_12ch @ sp+0x154
│ 0x00402030 d0febd27 addiu sp, sp, -0x130
│ 0x00402034 2c01bfaf sw ra, (var_12ch)
│ 0x00402038 2801b0af sw s0, (var_128h)
│ 0x0040203c 42001c3c lui gp, 0x42 ; 'B'
│ 0x00402040 f0a79c27 addiu gp, gp, -0x5810
│ 0x00402044 1000bcaf sw gp, (var_10h)
│ 0x00402048 3001a4af sw a0, (envp)
│ 0x0040204c 3401a5af sw a1, (arg_134h)
│ 0x00402050 2400a327 addiu v1, sp, 0x24
│ 0x00402054 00010224 addiu v0, zero, 0x100
│ 0x00402058 21206000 move a0, v1
│ 0x0040205c 21280000 move a1, zero
│ 0x00402060 21304000 move a2, v0
│ 0x00402064 6880828f lw v0, -sym.imp.memset(gp) ; [0x412858:4]=0x402460 sym.imp.memset ; "`$@"
│ 0x00402068 00000000 nop
│ 0x0040206c 21c84000 move t9, v0
│ 0x00402070 09f82003 jalr t9
│ 0x00402074 00000000 nop
│ 0x00402078 1000bc8f lw gp, (var_10h)
│ 0x0040207c 4000023c lui v0, 0x40 ; '@'
│ 0x00402080 f4264424 addiu a0, v0, 0x26f4 ; 0x4026f4 ; "UPLOAD_FILENAME" ; argc ; str.UPLOAD_FILENAME
│ 0x00402084 a880828f lw v0, -sym.imp.getenv(gp) ; [0x412898:4]=0x402370 sym.imp.getenv ; "p#@"
│ 0x00402088 00000000 nop
│ 0x0040208c 21c84000 move t9, v0
│ 0x00402090 09f82003 jalr t9
│ 0x00402094 00000000 nop
│ 0x00402098 1000bc8f lw gp, (var_10h)
│ 0x0040209c 1800a2af sw v0, (var_18h)
│ 0x004020a0 4000023c lui v0, 0x40 ; '@'
│ 0x004020a4 04274224 addiu v0, v0, 0x2704 ; 0x402704 ; "filename:%s\n" ; str.filename:_s_n
│ 0x004020a8 2400a327 addiu v1, sp, 0x24
│ 0x004020ac 21206000 move a0, v1
│ 0x004020b0 00010524 addiu a1, zero, 0x100 ; argv
│ 0x004020b4 21304000 move a2, v0 ; int32_t arg3
│ 0x004020b8 1800a78f lw a3, (var_18h) ; int32_t arg_138h
│ 0x004020bc 8880828f lw v0, -sym.imp.snprintf(gp) ; [0x412878:4]=0x4023e0 sym.imp.snprintf
│ 0x004020c0 00000000 nop
│ 0x004020c4 21c84000 move t9, v0
│ 0x004020c8 09f82003 jalr t9
│ 0x004020cc 00000000 nop
│ 0x004020d0 1000bc8f lw gp, (var_10h)
│ 0x004020d4 2400a227 addiu v0, sp, 0x24
│ 0x004020d8 21204000 move a0, v0 ; int32_t arg1
│ 0x004020dc 21280000 move a1, zero ; int32_t arg2
│ 0x004020e0 4a05100c jal fcn.00401528
│ 0x004020e4 00000000 nop
│ 0x004020e8 1000bc8f lw gp, (var_10h)
│ 0x004020ec 4000023c lui v0, 0x40 ; '@'
│ 0x004020f0 14275024 addiu s0, v0, 0x2714 ; 0x402714 ; "SERVER_SOFTWARE:%s\n" ; str.SERVER_SOFTWARE:_s_n
│ 0x004020f4 4000023c lui v0, 0x40 ; '@'
│ 0x004020f8 28274424 addiu a0, v0, 0x2728 ; 0x402728 ; "SERVER_SOFTWARE" ; str.SERVER_SOFTWARE
│ 0x004020fc a880828f lw v0, -sym.imp.getenv(gp) ; [0x412898:4]=0x402370 sym.imp.getenv ; "p#@"
│ 0x00402100 00000000 nop
│ 0x00402104 21c84000 move t9, v0
│ 0x00402108 09f82003 jalr t9
│ 0x0040210c 00000000 nop
│ 0x00402110 1000bc8f lw gp, (var_10h)
│ 0x00402114 2400a327 addiu v1, sp, 0x24
│ 0x00402118 21206000 move a0, v1
│ 0x0040211c 00010524 addiu a1, zero, 0x100
│ 0x00402120 21300002 move a2, s0 ; int32_t arg3
│ 0x00402124 21384000 move a3, v0 ; int32_t arg_138h
│ 0x00402128 8880828f lw v0, -sym.imp.snprintf(gp) ; [0x412878:4]=0x4023e0 sym.imp.snprintf
│ 0x0040212c 00000000 nop
│ 0x00402130 21c84000 move t9, v0
│ 0x00402134 09f82003 jalr t9
│ 0x00402138 00000000 nop
│ 0x0040213c 1000bc8f lw gp, (var_10h)
│ 0x00402140 2400a227 addiu v0, sp, 0x24
│ 0x00402144 21204000 move a0, v0 ; int32_t arg1
│ 0x00402148 21280000 move a1, zero ; int32_t arg2
│ 0x0040214c 4a05100c jal fcn.00401528
│ 0x00402150 00000000 nop
│ 0x00402154 1000bc8f lw gp, (var_10h)
│ 0x00402158 4000023c lui v0, 0x40 ; '@'
│ 0x0040215c 38274424 addiu a0, v0, 0x2738 ; 0x402738 ; "CONTENT_TYPE" ; str.CONTENT_TYPE
│ 0x00402160 a880828f lw v0, -sym.imp.getenv(gp) ; [0x412898:4]=0x402370 sym.imp.getenv ; "p#@"
│ 0x00402164 00000000 nop
│ 0x00402168 21c84000 move t9, v0
│ 0x0040216c 09f82003 jalr t9
│ 0x00402170 00000000 nop
│ 0x00402174 1000bc8f lw gp, (var_10h)
│ 0x00402178 1c00a2af sw v0, (var_1ch)
│ 0x0040217c 2000a0af sw zero, (var_20h)
│ 0x00402180 1c00a28f lw v0, (var_1ch)
│ 0x00402184 00000000 nop
│ ┌─< 0x00402188 0f004010 beqz v0, 0x4021c8
│ │ 0x0040218c 00000000 nop
│ │ 0x00402190 1c00a48f lw a0, (var_1ch)
│ │ 0x00402194 4000023c lui v0, 0x40 ; '@'
│ │ 0x00402198 48274524 addiu a1, v0, 0x2748 ; 0x402748 ; "boundary=" ; str.boundary
│ │ 0x0040219c 5080828f lw v0, -sym.imp.strstr(gp) ; [0x412840:4]=0x4024c0 sym.imp.strstr
│ │ 0x004021a0 00000000 nop
│ │ 0x004021a4 21c84000 move t9, v0
│ │ 0x004021a8 09f82003 jalr t9
│ │ 0x004021ac 00000000 nop
│ │ 0x004021b0 1000bc8f lw gp, (var_10h)
│ │ 0x004021b4 2000a2af sw v0, (var_20h)
│ │ 0x004021b8 2000a28f lw v0, (var_20h)
│ │ 0x004021bc 00000000 nop
│ ┌──< 0x004021c0 09004014 bnez v0, 0x4021e8
│ ││ 0x004021c4 00000000 nop
│ ││ ; CODE XREF from main @ 0x402188(x)
│ │└─> 0x004021c8 4000023c lui v0, 0x40 ; '@'
│ │ 0x004021cc 54274424 addiu a0, v0, 0x2754 ; 0x402754 ; "failed, can't find boundary=.\n" ; int32_t arg1 ; str.failed__cant_find_boundary._n
│ │ 0x004021d0 21280000 move a1, zero ; int32_t arg2
│ │ 0x004021d4 4a05100c jal fcn.00401528
│ │ 0x004021d8 00000000 nop
│ │ 0x004021dc 1000bc8f lw gp, (var_10h)
│ │┌─< 0x004021e0 b8081008 j 0x4022e0
│ ││ 0x004021e4 00000000 nop
│ ││ ; CODE XREF from main @ 0x4021c0(x)
│ └──> 0x004021e8 2000a28f lw v0, (var_20h)
│ │ 0x004021ec 00000000 nop
│ │ 0x004021f0 09004224 addiu v0, v0, 9
│ │ 0x004021f4 2000a2af sw v0, (var_20h)
│ │ 0x004021f8 4100023c lui v0, 0x41 ; 'A'
│ │ 0x004021fc 2000a38f lw v1, (var_20h)
│ │ 0x00402200 00000000 nop
│ │ 0x00402204 d42843ac sw v1, 0x28d4(v0)
│ │ 0x00402208 4000023c lui v0, 0x40 ; '@'
│ │ 0x0040220c 74274324 addiu v1, v0, 0x2774 ; 0x402774 ; "boundary:%s" ; str.boundary:_s
│ │ 0x00402210 4100023c lui v0, 0x41 ; 'A'
│ │ 0x00402214 d428428c lw v0, 0x28d4(v0)
│ │ 0x00402218 2400a427 addiu a0, sp, 0x24
│ │ 0x0040221c 00010524 addiu a1, zero, 0x100
│ │ 0x00402220 21306000 move a2, v1 ; int32_t arg3
│ │ 0x00402224 21384000 move a3, v0 ; int32_t arg_138h
│ │ 0x00402228 8880828f lw v0, -sym.imp.snprintf(gp) ; [0x412878:4]=0x4023e0 sym.imp.snprintf
│ │ 0x0040222c 00000000 nop
│ │ 0x00402230 21c84000 move t9, v0
│ │ 0x00402234 09f82003 jalr t9
│ │ 0x00402238 00000000 nop
│ │ 0x0040223c 1000bc8f lw gp, (var_10h)
│ │ 0x00402240 2400a227 addiu v0, sp, 0x24
│ │ 0x00402244 21204000 move a0, v0 ; int32_t arg1
│ │ 0x00402248 21280000 move a1, zero ; int32_t arg2
│ │ 0x0040224c 4a05100c jal fcn.00401528
│ │ 0x00402250 00000000 nop
│ │ 0x00402254 1000bc8f lw gp, (var_10h)
│ │ 0x00402258 1800a48f lw a0, (var_18h) ; int32_t arg1
│ │ 0x0040225c 0d06100c jal fcn.00401834
│ │ 0x00402260 00000000 nop
│ │ 0x00402264 1000bc8f lw gp, (var_10h)
│ ┌──< 0x00402268 09004010 beqz v0, 0x402290
│ ││ 0x0040226c 00000000 nop
│ ││ 0x00402270 4000023c lui v0, 0x40 ; '@'
│ ││ 0x00402274 80274424 addiu a0, v0, 0x2780 ; 0x402780 ; "failed, can't remove head tail.\n" ; int32_t arg1 ; str.failed__cant_remove_head_tail._n
│ ││ 0x00402278 21280000 move a1, zero ; int32_t arg2
│ ││ 0x0040227c 4a05100c jal fcn.00401528
│ ││ 0x00402280 00000000 nop
│ ││ 0x00402284 1000bc8f lw gp, (var_10h)
│ ┌───< 0x00402288 b8081008 j 0x4022e0
│ │││ 0x0040228c 00000000 nop
│ │││ ; CODE XREF from main @ 0x402268(x)
│ │└──> 0x00402290 1800a48f lw a0, (var_18h) ; int32_t arg1
│ │ │ 0x00402294 2303100c jal fcn.00400c8c
│ │ │ 0x00402298 00000000 nop
│ │ │ 0x0040229c 1000bc8f lw gp, (var_10h)
│ │┌──< 0x004022a0 09004014 bnez v0, 0x4022c8
│ │││ 0x004022a4 00000000 nop
│ │││ 0x004022a8 4000023c lui v0, 0x40 ; '@'
│ │││ 0x004022ac a4274424 addiu a0, v0, 0x27a4 ; 0x4027a4 ; "check fw header FAILED\r\n" ; int32_t arg1 ; str.check_fw_header_FAILED_r_n
│ │││ 0x004022b0 21280000 move a1, zero ; int32_t arg2
│ │││ 0x004022b4 4a05100c jal fcn.00401528
│ │││ 0x004022b8 00000000 nop
│ │││ 0x004022bc 1000bc8f lw gp, (var_10h)
│ ┌────< 0x004022c0 b8081008 j 0x4022e0
│ ││││ 0x004022c4 00000000 nop
│ ││││ ; CODE XREF from main @ 0x4022a0(x)
│ ││└──> 0x004022c8 21200000 move a0, zero
│ ││ │ 0x004022cc 5480828f lw v0, -sym.imp.exit(gp) ; [0x412844:4]=0x4024b0 sym.imp.exit
│ ││ │ 0x004022d0 00000000 nop
│ ││ │ 0x004022d4 21c84000 move t9, v0
│ ││ │ 0x004022d8 09f82003 jalr t9
│ ││ │ 0x004022dc 00000000 nop
│ ││ │ ; CODE XREFS from main @ 0x4021e0(x), 0x402288(x), 0x4022c0(x)
│ └└─└─> 0x004022e0 ffff0424 addiu a0, zero, -1
│ 0x004022e4 5480828f lw v0, -sym.imp.exit(gp) ; [0x412844:4]=0x4024b0 sym.imp.exit
│ 0x004022e8 00000000 nop
│ 0x004022ec 21c84000 move t9, v0
│ 0x004022f0 09f82003 jalr t9
│ 0x004022f4 00000000 nop
│ 0x004022f8 00000000 nop
└ 0x004022fc 00000000 nop
fwupload.cgi 정적 분석 결과 요약system() 함수가 존재 → 임의 명령 실행(RCE) 가능성"UPLOAD_FILENAME" 환경 변수를 사용 → 파일 업로드 취약점 가능성"boundary=" 문자열 확인 → HTTP Multipart Form 데이터 처리"check fw header FAILED" → 펌웨어 파일 검증 과정 존재system() 함수의 사용 방식?system() 호출이 0x00402380 주소에서 확인됨 (afl | grep system 결과)system()에 전달되는지 확인 필요!!main 함수에서 환경 변수 "UPLOAD_FILENAME"을 가져오고 있음0x00402080 f4264424 addiu a0, v0, 0x26f4 ; "UPLOAD_FILENAME"
0x00402084 a880828f lw v0, -sym.imp.getenv(gp)
getenv("UPLOAD_FILENAME")를 호출하여 값을 가져옴"UPLOAD_FILENAME" 값을 검증 없이 system()에 전달한다면 명령어 주입(Command Injection) 취약점 발생 가능system()이 UPLOAD_FILENAME을 통해 실행될 경우, 외부 입력을 통해 임의 명령어 실행 가능"&& malicious_command" 형태로 구성되면 쉘 명령어 실행이 가능할 수 있음"boundary="가 포함되어 있어 HTTP Multipart 업로드 처리를 수행 → 파일 업로드 취약점 가능성도 존재system() 호출부 추적pdg 명령으로 system()이 어디에서 호출되는지 확인UPLOAD_FILENAME 값이 system()에 직접 전달되는지 확인"check fw header FAILED"가 있는 부분이 system() 실행 전 수행되는지 확인