# [AIdrifter CS 浮生筆錄](https://hackmd.io/bKL1LVo8RaCKn02uHJW2BA#) : GNU Binary Utilities ## readelf - `Wl,-soname` 可以讓該so真正的名子跑出來`readelf -a` ```bash # all information readelf -a # GCC version readelf -p .comment # CPU version readelf -h # module version readelf -p .module_version libxxx.so # check link shared libraries readelf -a an_optee_test_pr30 | grep Shared Type: DYN (Shared object file) 0x00000001 (NEEDED) Shared library: [liblog.so] 0x00000001 (NEEDED) Shared library: [libplayready3.x.so] 0x00000001 (NEEDED) Shared library: [libc.so] 0x00000001 (NEEDED) Shared library: [libdl.so] # check link shared original name readelf -a an_optee_test_pr30 | grep SONAME ``` ## objdump ```bash # objdump # ASCII objdump -s ./Apps/install/Play/libPR.a # ammsebly language objdump -D .... https://wirelessr.gitbooks.io/working-life/content/gdbyu_objdump.html # check assembly faster /tools/arm/linaro-4.9.3-2014.11-arm-linux-gnueabihf/bin//arm-linux-gnueabihf-objdump -SD ****.so /* ** Extract <Records> node from the decrypted data. */ ChkDR( DRM_XML_GetSubNodeByPathA( pchDecryptedData, 6c65c: 4e69 ldr r6, [pc, #420] ; (6c804 <_ProcessMeterDataResponse+0x61c>) 6c65e: a923 add r1, sp, #140 ; 0x8c 6c660: 4638 mov r0, r7 6c662: 462b mov r3, r5 6c664: ac2d add r4, sp, #180 ; 0xb4 6c666: f85a 2006 ldr.w r2, [sl, r6] 6c66a: 9500 str r5, [sp, #0] 6c66c: 9501 str r5, [sp, #4] 6c66e: 9402 str r4, [sp, #8] 6c670: f8cd b00c str.w fp, [sp, #12] 6c674: f7c6 ef26 blx 334c4 <DRM_XML_GetSubNodeByPathA@plt> 6c678: f1b0 0c00 subs.w ip, r0, #0 6c67c: db5e blt.n 6c73c <_ProcessMeterDataResponse+0x554> NULL, NULL, &dasstrRecords, g_chForwardSlash ) ); ``` ## objcopy - This API only work when static libraries, you can not changed shared libraries ```bash # Add perfix to all fuction name and global variable objcopy --prefix-symbols=new_ libCCC.a # repalce oringinal symbol objcopy --redefine-sym=new_memcmp=memcmp libCCCC.a # add section for i in $(find ./output/*.so); do file_type=$(file $i | awk -F ' ' '{print $2}') if [[ "$file_type" == "ELF" ]]; then echo $BASE.$GIT_LABEL.$DATE$TIME > version_info if [ -z ${CROSS_COMPILE} ]; then # For Android Version echo "toolchain is android" else echo "toolchain is $CROSS_COMPILE" ${CROSS_COMPILE}objcopy --add-section .mmodule_version=version_info $i > /dev/null 2>&1 fi fi echo -e "\033[32m readelf -p .mmodule_version $i \033[0m" readelf -p .mmodule_version $i done ``` ## addr2line ```bash PC: /lib/libc-2.24.so [0x74a65bac] LR: /usr/lib/libadaptor.so.0.1.0 [0x759becd8] 754c8000-75a9a000 r-xp 00000000 b3:1f 146 /usr/lib/libadaptor.so.0.1.0 75a9a000-75aaa000 ---p 005d2000 b3:1f 146 /usr/lib/libadaptor.so.0.1.0 75aaa000-75b89000 rw-p 005d2000 b3:1f 146 /usr/lib/libadaptor.so.0.1.0 python >>> hex(0x759becd8-0x754c8000) '0x4f6cd8' $ addr2line -a -f -e ./libadaptor.so 0x4f6cd8 ``` ## gcc (GNU compiler collection) http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html ```bash # telling GCC where to find the shared library gcc -L/home/username/foo -Wall -o test main.c -lfoo # telling GCC where to find the header gcc -I ./ # How do I run the GCC preprocessor to get the code after macros like #define are expanded? gcc -E # stripe arm-none-linux-gnueabi-strip --strip-debug --remove-section=.note --remove-section=.comment libplayready_tee.so ``` ## check ARM gcc parameter Reference: http://www.keil.com/support/man/docs/armclang_ref/armclang_ref_ysm1476093575636.htm * -Wno-unused-function http://blog.csdn.net/findaway123/article/details/39646039 * -mfloat-abi=softfp * -Wno-pointer-to-int-cast * -fpie * -fstack-usage * -std=gnu99 * -Werror * -fdiagnostics-show-option Only meaningful in line-wrapping mode. Instructs the diagnostic messages reporter to emit source location information once; that is, in case the message is too long to fit on a single physical line and has to be wrapped, the source location will not be emitted (as prefix) again, over and over, in subsequent continuation lines. This is the default behavior. * -ffunction-sections generates a separate ELF section for each function in the source file. The unused section elimination feature of the linker can then remove unused functions at link time. The output section for each function has the same name as the function that generates the section, but with a .text. prefix. To disable this, use -fno-function-sections. * -fdata-sections If you compile this code with -fno-data-sections, you get: ```bash Symbol table .symtab (15 symbols, 10 local) # Symbol Name Value Bind Sec Type Vis Size ======================================================================== 8 .L_MergedGlobals 0x00000008 Lc 7 Data De 0x8 9 main.b 0x0000000c Lc 7 Data De 0x4 10 ... 11 ... 12 a 0x00000008 Gb 7 Data De 0x4 13 c 0x00000000 Gb 7 Data Hi 0x4 14 d 0x00000004 Gb 7 Data Hi 0x4 ... ``` If you compare the two Sec columns, you can see that when -fdata-sections is used, the variables are put into different sections. When -fno-data-sections is used, all the variables are put into the same sectio n. * -O0 * -g3 * -pipe * -mlong-calls Tells the compiler to perform function calls by first loading the address of the function into a register and then performing a subroutine call on this register. This switch is needed if the target function li es outside of the 64-megabyte addressing range of the offset-based version of subroutine call instruction. * GCC --hash-style=gnu :::success http://pank.org/blog/2007/10/gcc-hashstylegnu.html Fedora Core 6 以後, Mandriva 2007.1 以後, GCC 使用了新的預設參數 --hash-style=gnu, 據說可以提昇 50% 動態連結速度(dynamic linking speed), 缺點是無法和舊版的 glibc 及 dynamic # linker 相容, 所以用新參數編譯的程式無法在舊系統執行, 會出現 Floating point exception (core dumped) 若要使程式能在舊系統執行, 需在編譯時加 --hash-style=sysv 參數, 如: gcc -g -o hello -Wl,--hash-style=sysv hello.c ::: ## bt ```bash arm-none-linux-gnueabi-objdump -D libprov.so 0xb6a4376c <+1268>: b 0xb6a437bc <DRM_LA_ProcessLicenseV3+1348> ``` ## nm - show the C++ symbol ```bash nm -gC XXX.so ``` - Find symbol in obeject file and shared libraries quickly ```shell find . -type f \( -name "*.o" -o -name "*.so" \) -exec nm -A {} \; | grep "T funA" ``` ## strings - check string in elf file ```basH # strings strings - ./output/libcurl.so | grep aidrifter ``` - You can get pritnf message via `strings` ```info Set-Cookie: # Netscape HTTP Cookie File # http://curl.haxx.se/docs/http-cookies.html # This file was generated by libcurl! Edit at your own risk. # Fatal libcurl error WARNING: failed to save cookies in %s http_should_fail copy_header_value https_connecting Curl_http_output_auth Curl_add_buffer_send ``` ## ldd - show linked sequence ```shell aidrifter@aidrifter-VM$ ldd /bin/ls linux-vdso.so.1 => (0x00007ffd565a7000) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fa5a6c3c000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa5a6875000) libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fa5a6602000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa5a63fe000) /lib64/ld-linux-x86-64.so.2 (0x000055a30d844000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa5a61e0000) ``` ## lddtree - Support Android System, show libraries hierarchy ``` lddtree /bin/ls ls => /bin/ls (interpreter => /lib64/ld-linux-x86-64.so.2) libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 libpcre.so.3 => /lib/i386-linux-gnu/libpcre.so.3 libdl.so.2 => /lib/i386-linux-gnu/libdl.so.2 ld-linux.so.2 => /lib/i386-linux-gnu/ld-linux.so.2 libacl.so.1 => /lib/x86_64-linux-gnu/libacl.so.1 libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 libc.so.6 => /lib/i386-linux-gnu/libc.so.6 ``` ## gcc parameter - start group and end group https://medium.com/fcamels-notes/linux-%E7%B7%A8%E8%AD%AF-shared-library-%E7%9A%84%E6%96%B9%E6%B3%95%E5%92%8C%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85-cb35844ef331 - wl, whole architecture https://stackoverflow.com/questions/805555/ld-linker-question-the-whole-archive-option