Kết thúc đồ án tốt nghiệp và quay trở lại với công việc thường ngày, mình được giao job hỗ trợ audit 1 product IoT. Do tâm trạng còn đang rối bời nên ko dám nhận xử lý chính vụ này.

Policy của bên X (bên yêu cầu audit) hơi ngặt nghèo và cồng kềnh vô lý, do đó bọn mình ko thể có đc source code của product để audit thực tế. Bên họ cho người xách 1 con lap chứa source code sang, bắt team audit bằng cơm … nhưng đó chưa là gì, ngày xưa họ còn in code ra giấy thành 7 quyển, mỗi quyển dày 5–7 cm và xách sang cho mình đọc cơ =)))). Job thì đã lỡ nhận rồi nên team mình vẫn phải làm thôi, kết quả thì cũng ko tìm ra đc nhiều thứ lắm.

Đành dựa vào một số kỹ năng ngoại cảm, mình tìm được một bộ source code giống giống với bộ này ở trên github, và đó là lý do có bài viết này!

Bộ source code mình tìm được trên github là đây: https://github.com/weihutaisui/BCM

Vào thời điểm của bài viết thì nó vẫn tồn tại trên github với hình thù như sau:

Mình ko rõ tại sao github chưa gỡ cái repo này xuống, do firmware này có 1 số phần code bị dính bản quyền của broadcom, trước đó đã từng thấy nhiều source code của firmware bị up lên github nhưng đều bị gỡ xuống vì dính cái bản quyền này rồi.

Trong bài viết này mình sẽ viết về các tình huống gặp phải khi build và cách xử lý chúng,

#Environment
Môi trường thực hiện build:

  • Ubuntu 18.04 (cái base OS để build rất quan trọng, có thể OS khác sẽ không hỗ trợ 1 số lib trong quá trình build!), ở đây mình setup docker cho nó trực quan

Mình kết hợp sử dụng docker trên windows và VS Code cho nó tiện, có thể open cả cái container trong VS Code như vầy:

Để build được thì việc đầu tiên là phải add cái architecture i386, apt update và cài thêm 1 số công cụ cần thiết như nano, git, make, gcc … vì container này hoàn toàn trắng, ko có các công cụ này như bản setup thông thường:

dpkg --add-architecture i386 && apt update && apt install -y locales nano git make autoconf gcc g++ xxd libz-dev wget file gcc-multilib g++-multilib autoconf

Việc tiếp theo là clone cái project kia về thôi:

git clone https://github.com/weihutaisui/BCM/

(Có thể project sẽ bay màu trong tương lai, nên backup lại để sau này có thể dùng tiếp…)

Để ý trong folder có file “Makefile”, theo bản năng thì mình cứ thế gõ make thôi, mất gì đâu nhỉ … ¯\_(ツ)_/¯.

#Round 1: Fix lỗi SHELL environment

Và đây là lỗi đầu tiên khi gõ “make”:

Gặp ngay cái lỗi này:

ERROR: /bin/sh does not invoke bash shell ....

Có lẽ cũng giống như bao người khác, mình copy paste cái lỗi này lên google, hy vọng xem có 1 đáp án phù hợp nào đó ở stackoverflow ko ¯\_( ͡° ͜ʖ ͡°)_/¯

blo bla …

Nói chung là search vẫn ra vô vàn kết quả, nhưng trong đó ko có cái nào giúp ích cả đâu =))).

Sau một thời gian đọc lại Makefile thì mình đã fix được bằng cách như sau:

Mở lại Makefile ở root folder (folder ngoài cùng của source code ý), thêm dòng:

SHELL=/bin/bash

Vào đầu của Makefile, sau khi sửa file có dạng như sau:

#Round 2: Bỏ qua đoạn check user root

Sửa xong thì tiếp tục make lần nữa, lần này thì gặp lỗi như sau:

ERROR: Attempting to build as root.

Cái này là do trong make.common có dòng check để tránh việc build project với quyền root, nhưng mình đang build trên docker nên việc này có thể bỏ qua được bằng cách bỏ đoạn check nó đi:

#Round 3: Fix quyền executable

Tiếp tục make sau khi bỏ qua đoạn kiểm tra user sẽ gặp lỗi như sau:

/bin/bash: /root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/checkver.pl: Permission denied

Nghĩa là file “checkver.pl” kia đang ko có quyền execute:

Có thể trong quá trình nén file hoặc push lên github, quyền execute của các file thực thi đều đã bị remove hết, cần phải tìm lại những file này và grant lại quyền cho chúng. Trong quá trình build thì mình đã tìm ra được hết các file cần sửa quyền và tổng hợp vào 1 đoạn script để fix quyền như sau:

find . -iname "*.pl" -exec chmod +x {} \;
find . -iname "*.sh" -exec chmod +x {} \;
find . -iname "configure" -exec chmod +x {} \;
find . -iname "gen_dt_bindings" -exec chmod +x {} \;
find . -iname "gendefconfig" -exec chmod +x {} \;

#Round 4: Fix locale + lzo library:

Tiếp tục make sau khi đã sửa quyền, và đương nhiên là lại gặp lỗi rồi

perl: warning: Please check that your locale settings:
        LANGUAGE = (unset),
        LC_ALL = (unset),
        LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
1.29
<stdin>:1:10: fatal error: lzo/lzo1x.h: No such file or directory
compilation terminated.
ERROR: lzo/lzo1x.h development library is required for build
       usually, this is provided by the liblzo2-dev library

Lượn 1 vòng google thì tìm được cách fix lỗi locale tại đây: https://snippets.aktagon.com/snippets/614-how-to-fix-bash-warning-setlocale-lc-all-cannot-change-locale-en-us-

Fix đơn giản bằng cách sửa file /etc/default/locale, thay thế nội dung bằng:

LANGUAGE = (unset),
LC_ALL = (unset),
LANG = "en_US.UTF-8"

Thay thế xong thì gõ

locale-gen en_US.UTF-8

Và lỗi của locale ko còn tồn tại nữa

Tới lỗi của liblzo2, fix bằng cách cài thêm gói này thôi, (mình cài thêm cả package cho i386 để chắc ăn hơn):

apt install -y liblzo2-dev liblzo2-dev:i386

#Round 5: Thiếu gói uuid

Make tiếp thì lại gặp lỗi

ERROR: libuuid development library is required for build

Cài thêm libuuid bằng lệnh sau:

apt install -y libuuid1 libuuid1:i386 uuid-dev uuid-dev:i386

#Round 6: Thiếu pkg-config

Và như dự đoán, make tiếp thì lại gặp lỗi thôi ?‍♀️.

Mình mất cả 1 ngày dài xoắn não với cái đống này để đọc và fix lỗi, thôi tiếp tục nào:

/bin/bash: pkg-config: command not found
ERROR: pkg-config zlib failed

Thiếu cái gì thì cài cái đó, tiếp tục cài pkg-config vào nào:

apt install -y pkg-config

#Round 7: Chọn profile để build

Sau khi cài được pkg config, thì nó ko còn bắt lỗi nhiều nữa, chỉ suggest thêm như sau:

You need to specify build profile name from /root/BCM/HGU_BCM68580/02_src_502L04patch2/targets using 'make PROFILE=<profile name>...'

Trong folder “targets” có chứa các PROFILE đặc biệt cho từng dòng chip broadcom khác nhau,

Mình chọn bừa lấy 1 chip trong này, ví dụ như “96838GWO” đi, vì thực tế thì mình cũng ko quan tâm sẽ build được firmware hay ko. Mình chỉ quan tâm là có thể build đc cái httpd và vứt vào Semmle cho nó quét lỗi thôi ?‍♀️. Chọn được profile rồi thì export nó ra 1 cái biến môi trường cho tiện:

export PROFILE=96838GWO

#Round 8: setup toolchain

Lỗi mới gặp ngay sau khi set profile:

ERROR: could not find Toolchain
/opt/toolchains//crosstools-mips-gcc-5.3-linux-4.1-uclibc-1.0.12-binutils-2.25-NPTL

Search keyword “crosstools-arm-gcc-5.3-linux-4.1-glibc-2.24-binutils-2.25” trên google loanh quanh thì mình tìm được trang này chứa nhiều toolchain hay ho: https://download.iopsys.eu/iopsys/toolchain/

Kéo về đúng folder toolchains thôi

mkdir -p /opt/toolchains && cd /opt/toolchains/ && wget

https://download.iopsys.eu/iopsys/toolchain/crosstools-mips-gcc-5.3-linux-4.1-uclibc-1.0.12-binutils-2.25-NPTL.Rel1.8.tar.bz2

 && tar -xf crosstools-mips-gcc-* && mv /opt/toolchains/opt/toolchains/crosstools-mips-gcc-5.3-linux-4.1-uclibc-1.0.12-binutils-2.25-NPTL /opt/toolchains/

#Round 9: sửa quyền executable của script gendefconfig

Sau khi sửa đc toolchain thì lần make tới sẽ lâu hơn vì đã qua được đoạn check ban đầu, ta sẽ dừng tại lỗi sau:

Untarring original Linux kernel source: src-linux-4.1.tar.bz2
/root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/gendefconfig: line 10: /root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/gendefconfig.d/10kernel.conf: Permission denied
/root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/gendefconfig: line 10: /root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/gendefconfig.d/15general.conf: Permission denied
/root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/gendefconfig: line 10: /root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/gendefconfig.d/20flashfs.conf: Permission denied

Các file này cần phải thực thi nhưng lại ko có quyền, fix lại tương tự như cách fix mấy cái script .pl ban đầu

find /root/BCM/HGU_BCM68580/02_src_502L04patch2/hostTools/scripts/gendefconfig.d/ -type f -exec chmod +x {} \;

#Round 10: fix lỗi build kernel

Tiếp tục build sẽ gặp một số lỗi “command not found”:

./make_version.sh: line 15: dos2unix: command not found
./make_version.sh: line 21: dos2unix: command not found
/root/BCM/HGU_BCM68580/02_src_502L04patch2/bcmdrivers/broadcom/net/wl/bcm96846/main/src/wl/config/wlconfig_lx_wl_dslcpepcisdcfg:20: ===Include= wlconfig_lx_router_ap======
make[3]: 'include/generated/mach-types.h' is up to date.
make[5]: warning: -jN forced in submake: disabling jobserver mode.
/root/BCM/HGU_BCM68580/02_src_502L04patch2/bcmdrivers/broadcom/net/wl/bcm96838/main/src/wl/config/wlconfig_lx_wl_dslcpepcisdcfg:20: ===Include= wlconfig_lx_router_ap======
  CHK     include/generated/bounds.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  BC      kernel/time/timeconst.h
/bin/sh: 1: bc: not found

Đơn giản là cài thêm mấy cái này thôi:

apt install -y bc dos2unix

#Round 11: Build userspace

Công việc từ đầu tới giờ chỉ là các bước để setup các thứ cần thiết cho build cái userspace này thôi, để build cái userspace này, sử dụng lệnh:

make userspace

Khi đó sẽ chỉ build mỗi userspace, bỏ qua các bước build kernel rườm rà xung quanh!

Ngay khi make userspace sẽ gặp lỗi sau:

configure: error: Neither flex nor lex was found.
Makefile:31: recipe for target 'objs/arm/Makefile' failed
make[2]: *** [objs/arm/Makefile] Error 1
make[2]: Leaving directory '/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/public/libs/libpcap'
makefile.modsw.autogen:318: recipe for target 'public/libs/libpcap' failed

Khắc phục bằng cách cài thêm gói flex và bison (google họ bảo vậy):

apt install -y flex bison

#Round 12: Fix lỗi SHELL

Lần build này vẫn sẽ có lỗi, nhưng rất rối và khó để mà tìm được thực tế lỗi ở đâu:

Log gần nhất chỉ báo là lỗi, để tìm được lỗi thực tế ở đâu thì cần phải kéo về trước đó để tìm. Sau khi kéo log và tìm bằng cơm một hồi, có thể tìm thấy lỗi thực tế như sau:

rc3-install:  S46wl-setup-threads
scripts-install:  procbcmlog/bcmlog procbcmlog/spitr
/bin/sh: 4: Bad substitution
mkdir -p /root/BCM/HGU_BCM68580/02_src_502L04patch2/targets/96846GWO/fs.install/bin
make -C public/libs/expat
install -m 755 libnetlink_app /root/BCM/HGU_BCM68580/02_src_502L04patch2/targets/96846GWO/fs.install/bin
/bin/sh: 2: Bad substitution
/bin/sh: 6: Bad substitution
Makefile:57: recipe for target 'rc3-install' failed
make[2]: *** [rc3-install] Error 2
make[2]: Leaving directory '/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/public/apps/scripts'
makefile.modsw.autogen:150: recipe for target 'public/apps/scripts' failed

Như vậy có thể xác định được lỗi xảy ra tại rc3-install của file “/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/public/apps/scripts/Makefile”,

Tâm linh một hồi thì mình đã tìm ra nguyên nhân của lỗi “/bin/sh: 6: Bad substitution”.

Đáng ra trong môi trường build này thì shell phải là /bin/bash, nhưng ko hiểu sao ở đây lại là /bin/sh. Fix đơn giản bằng cách set lại SHELL ở đây là được:

#Round 13: fix lỗi thiếu libstdint.h

Tương tự như với round trước, lần này cũng phải kéo mãi lên trên mới có thể thấy được lỗi:

bpmctl_api.c: In function ‘bpmctl_ioctl’:
bpmctl_api.c:102:43:

error: ‘uintptr_t’ undeclared (first use in this function)

     if ( (ret = ioctl( devFd, ioctl_cmd, (uintptr_t) arg )) == BPMCTL_ERROR )
                                           ^
bpmctl_api.c:102:43: note: each undeclared identifier is reported only once for each function it appears in
bpmctl_api.c:102:54: error: expected ‘)’ before ‘arg’
     if ( (ret = ioctl( devFd, ioctl_cmd, (uintptr_t) arg )) == BPMCTL_ERROR )

Có lẽ là do lỗi của crosstools, sửa lại bằng cách thêm vào đầu file bpmctl_api.c:

#include <stdint.h>

#Round 14: Fix lỗi thiếu stdint.h

Lỗi của round này nằm ở “gpl/apps/iproute2”

Makefile:61: recipe for target 'all' failed
make[3]: *** [all] Error 2
make[3]: Leaving directory '/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/gpl/apps/iproute2/iproute2-4.3.0'
Makefile:54: recipe for target 'iproute2-4.3.0' failed
make[2]: *** [iproute2-4.3.0] Error 2
make[2]: Leaving directory '/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/gpl/apps/iproute2'
makefile.modsw.autogen:1439: recipe for target 'gpl/apps/iproute2' failed
make[1]: *** [gpl/apps/iproute2] Error 2
make[1]: *** Waiting for unfinished jobs....

Theo như mình dự đoán, lỗi của nó cũng tương tự như round trước, do file tc_core.c thiếu dòng include stdint.h.

Fix tương tự như round trước, thêm dòng khai báo include stdint.h vào đầu file

#Round 15: Fix lỗi library conflic

Tiếp tục build sẽ gặp lỗi tại “private/libs/cms_core”

/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/private/libs/wlcsm/src/wlcsm_lib_nvram.c:447: multiple definition of `wlcsm_nvram_commit'
../wlcsm/libwlcsm.a(wlcsm_lib_nvram.o):/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/private/libs/wlcsm/src/wlcsm_lib_nvram.c:447: first defined here

Có vẻ như đây là conflic thư viện, xử lý bằng cách bỏ 1 trong 2 cái này khỏi Makefile là được.

Trong “userspace/private/libs/cms_core/Makefile”, tìm và comment dòng sau:

STATIC_LIBS = ../wlcsm/libwlcsm.a

Kết quả được:

#Round 16: Fix lỗi thiếu library wlcsm

Tiếp tục gặp lỗi, bây giờ là lỗi của dropbear:

configure: error: in `/root/BCM/HGU_BCM68580/02_src_502L04patch2/userspace/public/apps/dropbear/dropbear-2016.74':
configure: error: C compiler cannot create executables
See `config.log' for more details
Makefile:64: recipe for target 'check_untar_patch_configure' failed

Ở đây ko có log cụ thể của quá trình build, theo như chỉ dẫn, mình đọc tiếp config.log để xem lỗi chính xác là ở đâu. Trong file config.log có báo lại rất nhiều lỗi, nhưng chung quy lại lỗi xuất phát ở đây:

warning: libwlcsm.so, needed by /root/BCM/HGU_BCM68580/02_src_502L04patch2/targets/96838GWO/fs.install/lib/libcms_cli.so, not found (try using -rpath or -rpath-link)

Lỗi như vậy chứng tỏ library wlcsm không có trong path để compile, check lại command để build như sau:

/opt/toolchains//crosstools-mips-gcc-5.3-linux-4.1-uclibc-1.0.12-binutils-2.25-NPTL/usr/bin/mips-buildroot-linux-uclibc-gcc  ... conftest.c -lcms_cli -lcms_dal -lcms_msg -lcms_core -lcms_qdm -lnanoxml -ldl -lgponctl -lgponif -lomciutil -lbcmipc -lvlanctl -lpwrctl -lethswctl -lethctl -leponctl -lm -lbridgeutil -lrdpactl -ltmctl -lbdmf -lbcmmcast -lcms_util -lbcm_crc -lbcm_flashutil -lbcm_boardctl -lcrypt >&5

Đúng như dự đoán, trong command này còn thiếu -lwlcsm để include lib này vào khi compile.

Fix bằng cách sửa Makefile trong “userspace/public/apps/dropbear”, thêm -lwlcsm tại dòng 19:

  • Thực tế thì khi build tiếp về sau sẽ gặp thêm nhiều trường hợp bị thiếu wlcsm tương tự:

Do đó để fix triệt để, cần thêm -lwlcsm vào CMS_COMMON_LIBS trong file make.common như sau:

#Round 17: Fix lỗi thiếu library gponctl

Tiếp tục gặp lỗi build tại “/userspace/private/apps/gpond”

Tương tự như lỗi của phần trước, đây là báo lỗi do thiếu library, cụ thể hơn là thiếu library gponctl.

Kiểm tra trong “/userspace/private/apps/gpond/Makefile.fullsrc”, có thể thấy ở đây đã có khai báo một lệnh if else để cho include cái library gponctl này vào. Có lẽ là trong config của PROFILE này không có BUILD_GPONCTL nên điều kiện này ko bao giờ thỏa mãn.

Fix bằng cách comment dòng check điều kiện đi là được ¯\_(ツ)_/¯.

#Finished

Sau khi fix tất tần tật các lỗi trên thì việc build userspace đã hoàn thiện:

Và việc tiếp theo là đưa vào cho Semmle build database để query thôi!

Phía trên mình đã viết về cách thứ build 1 bộ mã nguồn lượm nhặt đc trên github. Có thể trong thực tế, với môi trường khác nhau, hoàn cảnh khác nhau thì các lỗi xảy ra cũng sẽ khác nhau, nhưng chung quy lại đều cần tới sự tỉ mỉ, kỹ lưỡng để rà bug và fix.

Hy vọng sẽ giúp ích được các developer/researcher trong quá trình nghiên cứu.

Cảm ơn các bạn đã theo dõi!

__Jang__

 

1.063 lượt xem