{ "cells": [ { "attachments": {}, "cell_type": "markdown", "id": "4ff3e55b-7932-4294-955f-7d6ee9df8b13", "metadata": {}, "source": [ "# Symbol Porting\n", "\n", "## Introduction\n", "\n", "Porting symbols from one binary to another is a standard using case in diffing.\n", "Indeed, it is handy in reverse-engineering to apply function symbols to a stripped\n", "binary if we are able to put our hands on a similar binary with symbols.\n", "\n", "For the purpose of this practical we are going to use to versions of ``libsensorservice.so``\n", "for which the second version has been stripped." ] }, { "cell_type": "raw", "id": "2c0d6a18-0fee-43a4-8a89-0509b960bdaf", "metadata": {}, "source": [ "

binary

" ] }, { "cell_type": "raw", "id": "6c35b594-c8ec-4c83-b80e-c7927d08c5ee", "metadata": {}, "source": [ "
\n", "

Question

\n", "

Script the diff with python-bindiff and port the symbols to the second one with LIEF.\n", "

\n", "
" ] }, { "attachments": {}, "cell_type": "markdown", "id": "69aa55d0-e03b-4466-b3b3-3322c0384e2c", "metadata": {}, "source": [ "## I. Performing the diff\n", "\n", "To perform the diff with `python-bindiff` we first need to export the two binaries.\n", "\n", "If we don't have BinExport files we can perform the diff from the binaries with:" ] }, { "cell_type": "code", "execution_count": null, "id": "8e7f74e0-6d46-42cb-9503-7b7460dd0d9a", "metadata": {}, "outputs": [], "source": [ "from bindiff import BinDiff\n", "\n", "diff = BinDiff.from_binary_files(\"libsensorservice-1.so\", \"libsensorservice-2.so\", \"result.BinDiff\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3833fe46-7325-49fc-886a-7df906af25a7", "metadata": {}, "source": [ "If we already have the BinExport files, we can perform the diff with:" ] }, { "cell_type": "code", "execution_count": 13, "id": "49cde975-0585-47b1-bb0b-eb884c3540fc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from bindiff import BinDiff\n", "\n", "diff = BinDiff.from_binexport_files(\"libsensorservice-1.so.BinExport\", \"libsensorservice-2.so.BinExport\", \"result.BinDiff\")\n", "diff" ] }, { "attachments": {}, "cell_type": "markdown", "id": "0441acd8-5095-4999-a4b5-2a1bcf607f75", "metadata": {}, "source": [ "**Exercise**: Print the matches using the ``function_matches`` attributes" ] }, { "cell_type": "raw", "id": "eb8667ff-3c32-40cb-9b5b-121983f48e30", "metadata": {}, "source": [ "" ] }, { "cell_type": "code", "execution_count": 25, "id": "9f42909a-5a13-44c3-b314-64fe915a72d5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0x016560:__on_dlclose --> 0x016580:start\n", "0x016570:__emutls_unregister_key --> 0x016590:sub_00016590\n", "0x016580:__on_dlclose_late --> 0x0165a0:j_nullsub_1\n", "0x016590:android::BatteryService::BatteryService(void) --> 0x0165b0:sub_000165B0\n", "0x0165d0:android::BatteryService::enableSensorImpl(uint,int) --> 0x0165f0:sub_000165F0\n", "0x0166c0:android::BatteryService::checkService(void) --> 0x0166e0:sub_000166E0\n", "0x0167f0:android::BatteryService::disableSensorImpl(uint,int) --> 0x016810:sub_00016810\n", "0x0168d0:android::BatteryService::cleanupImpl(uint) --> 0x0168f0:sub_000168F0\n", "0x0169a0:android::Mutex::~Mutex() --> 0x0169c0:j__pthread_mutex_destroy\n", "0x0169b0:android::SortedVector::~SortedVector() --> 0x0169d0:sub_000169D0\n" ] } ], "source": [ "for m in diff.function_matches[:10]:\n", " print(f\"{m.address1:#08x}:{m.name1} --> {m.address2:#08x}:{m.name2}\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "968ff3b6-0dcc-44bd-a51f-c32aaacb620d", "metadata": {}, "source": [ "**Note**: Names are demangled here! To add symbols we will need to add mangled names." ] }, { "attachments": {}, "cell_type": "markdown", "id": "bfee8305-38e3-4367-a805-2316284b2d42", "metadata": {}, "source": [ "## II. Loading symbols\n", "\n", "We now need to load symbols from the two ELF binaries to be able to port from one to the\n", "other using diff information. Let's do this using [LIEF](https://lief.quarkslab.com) that enables\n", "parsing and modifying ELF binaries. We are going to add static symbols for our purpose here.\n", "\n", "**Exercise**: Load the two programs using LIEF, and compute a dictionary of address -> mangled name for the first binary." ] }, { "cell_type": "raw", "id": "27eee827-093d-490a-ae58-14c3c853462b", "metadata": {}, "source": [ "" ] }, { "cell_type": "code", "execution_count": 38, "id": "f9d21935-fbe4-4d54-8949-149fd8f715d8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0x000000: strdup\n", "0x041850: __dso_handle\n", "0x016560: __on_dlclose\n", "0x016580: __on_dlclose_late\n", "0x000270: abitag\n", "0x016570: __emutls_unregister_key\n", "0x016d30: _GLOBAL__sub_I_BatteryService.cpp\n", "0x0169d0: _ZN7android12SortedVectorINS_14BatteryService4InfoEED0Ev\n", "0x0169b0: _ZN7android12SortedVectorINS_14BatteryService4InfoEED2Ev\n", "0x0168d0: _ZN7android14BatteryService11cleanupImplEj\n" ] } ], "source": [ "import lief\n", "\n", "binary1 = lief.parse(\"libsensorservice-1.so\")\n", "binary2 = lief.parse(\"libsensorservice-2.so\")\n", "\n", "symbols = {s.value: s for s in binary1.static_symbols}\n", "\n", "for addr, sym in list(symbols.items())[:10]:\n", " print(f\"{addr:#08x}: {sym.name}\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "a4070080-c691-435a-8e99-453fb662f50e", "metadata": {}, "source": [ "## III. Porting symbols\n", "\n", "We can now assemble everything together to port symbols to ``binary2`` by using:\n", "\n", "* [add_static_symbol(sym)](https://lief-project.github.io/doc/latest/api/python/elf.html#lief.ELF.Binary.add_static_symbol) to add a symbol to an ELF\n", "* [write(s)](https://lief-project.github.io/doc/latest/api/python/elf.html#lief.ELF.Binary.write) to export a new ELF file\n", "\n", "**Exercise**: Use diffing result to add symbols to the second binary" ] }, { "cell_type": "raw", "id": "0c7450ec-2a0d-4df9-9787-eae9f39d7a84", "metadata": {}, "source": [ "" ] }, { "cell_type": "code", "execution_count": 39, "id": "acf8edb8-df4e-4da1-b2ff-369773173abb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "new library created: libsensorservice-2-with-symbols.so\n" ] } ], "source": [ "sym = lief.Symbol()\n", "for match in diff.function_matches:\n", " if match.address1 in symbols:\n", " # Create the symbol\n", " sym = symbols[match.address1]\n", " sym.value = match.address2\n", " binary2.add_static_symbol(sym)\n", "\n", "# Save the patched binary\n", "s = \"libsensorservice-2-with-symbols.so\"\n", "binary2.write(s)\n", "print(f\"new library created: {s}\")" ] }, { "attachments": {}, "cell_type": "markdown", "id": "d50db0e7-b3ae-484e-af42-40132cccca17", "metadata": {}, "source": [ "By loading at the generated shared library the result is the following:" ] }, { "cell_type": "raw", "id": "9398454f-11c4-4c3b-bcba-c39256df9e47", "metadata": {}, "source": [ "
\n", " \"symbols\n", "
" ] }, { "cell_type": "raw", "id": "4690bca0-bff1-492c-8f98-3392b9b61b7d", "metadata": {}, "source": [ "" ] } ], "metadata": { "kernelspec": { "display_name": "diffing", "language": "python", "name": "diffing" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.9" } }, "nbformat": 4, "nbformat_minor": 5 }