Hot answers tagged

40

TL;DR: machine code decompilers are very useful, but do not expect the same miracles that they provide for managed languages. To name several limitations: the result generally can't be recompiled, lacks names, types, and other crucial information from the original source code, is likely to be much more difficult to read than the original source code minus ...


24

General Prerequisites When analyzing binaries, it is important to be able to put what is observed into context. For example, how can CPU instructions be differentiated from data in a binary with a non-standard format? This requires some background knowledge of computer systems in general. I would argue that before any attempt at reverse engineering firmware ...


13

After decompressing and loading the kernel, you need to find a couple of tables that encode the compressed symbol table. These are (in the usual order they are placed in binary): kallsyms_addresses - a table of addresses to all public symbols in the kernel kallsyms_num_syms - not a table but just an integer with total number of symbols (should match ...


11

There is SmartDec, a native-code to C/C++ decompiler. It has two versions. Standalone and plugin to IDA. The latter supports all IDA's architectures, provides full GUI integration - is easy to work with -, makes use of IDA Flirt signatures and will make use of runtime information if you use it together with funcap. There is also Retargetable Decompiler, an ...


10

DARM (GitHub) by Jurriaan Bremer is an ARMv7 disassembler written in C and is available under a 3-Clause BSD License. Note: It currently does not support Thumb mode. A simple example of using DARM could be as follows: // The structure which will hold all the metadata about the disassembled instruction... darm_t d; // disassemble a 32bit opcode... if( ...


10

While the "GCC compiler" may be the same software (generally speaking), the specific instances used for compiling code here and there can produce quite different output. when compiling GCC itself, you can set hundreds of options, many of them influencing the generated code. even after building the compiler, every specific compile may use additional options, ...


9

Yes, it's because of pipelining. From http://winarm.scienceprog.com/arm-mcu-types/how-does-arm7-pipelining-works.html -- PC (Program Counter) is calculated 8 bytes ahead of current instruction.


9

You mentioned that you do have a running kernel available. It is possible to obtain symbol information from a running kernel by reading /proc/kallsyms. On newer distributions, this information is disabled by default for security reasons (all symbols will be displayed as 0x0 addresses), but you can manually enable it by running the following command as root:...


9

The extra s character added to the ARM instruction mean that the APSR (Application Processor Status Register) will be updated depending on the outcome of the instruction. The status register (APSR) contain four flags N, Z, C and V which means the following: N == 0: The result is greater or equal to 0, which is considered positive, and so the N (negative) ...


9

Update: See this answer for up-to-date information on where ARM64 syscall definitions are found. Note that the information below may just be for backwards-compatibility. See arch/arm64/include/asm/unistd32.h: ... #define __NR_restart_syscall 0 __SYSCALL(__NR_restart_syscall, sys_restart_syscall) #define __NR_exit 1 __SYSCALL(__NR_exit, sys_exit) #...


9

arm64 syscall numbers are defined at: https://github.com/torvalds/linux/blob/v4.17/include/uapi/asm-generic/unistd.h This is a bit confusing since it is quite different from x86 and x86_64 and arm which define syscall numbers under arch/, but that file has a comment saying: New architectures should use this file and implement the less feature-full calls ...


9

There're two broad ways in which you can declare JNI functions. The first is the more obvious way in which the JNI function has to follow a specific naming convention like JNIEXPORT void JNICALL Java_com_app_foo_bar. You can easily identify such functions using readelf. The other not so obvious way is to use RegisterNatives. Here your functions can have ...


8

An ARM object file should contain symbols identifying the regions that are arm code ($a), thumb code ($t) and literal data ($d). You can see these as symbols #4 and #5 in your read-elf output. i.e. offset 0 is arm, offset 8 is thumb obj-dump will output these symbols too if you use the--special-symsoption. Reading the ARM ELF ABI will help you understand ...


8

Currently you can't decrypt iOS apps without a device. The encryption keys are ultimately protected by an unknown key which is burned into the processor and cannot be extracted using software, that's why no "offline" decryption app has been made.


8

If it is ARM architecture that may use THUMB encoding it can be result of the following issue: If I remember correctly, calls to the virtual functions can be executed with assembly command similar to BLX as indirect jump, which allows switching between ARM and THUMB encoding. In this case this + 1 means that the target of the jump is encoded in THUMB. See ...


8

So, I have figured it out myself in the end. I'll try to describe the process. First, a bit of background on NAND: it is organized in pages which are grouped into blocks. You can read or write a single page at a time but erasing (which turns all bits to 1s (so bytes to FFs)) can be only done one block at a time (writing can only change bits from 1 to 0 but ...


7

Here's what IDA considers a return in ARM: RET (=MOV PC, LR) POP {reglist} if reglist includes LR or PC LDMFD SP, {reglist}, LDMED SP, {reglist} or LDMDB R11, {reglist} if reglist includes LR or PC LDR PC, [SP], #4 BX LR BX reg if preceded by POP {reglist} and reglist includes reg.


7

Usual ADD doesn't update flags. ADDS does. See better documentation at arm infocenter. As it wrote there: If S is specified, these instructions update the N, Z, C and V flags according to the result.


7

Libraries like STL or Boost are tricky. Because they're heavily template-based and most of their code is generated at compile time, it's pretty difficult to make FLIRT-style signatures for them. Too much depends on the specific compiler, build options, optimization settings and so on, so unless you match them pretty closely when generating signatures, you're ...


7

Decompilation is difficult because decompilers must recover source-code abstractions that are missing from the binary/bytecode target. There are several types of abstractions: Functions: The identification of code corresponding to a high function, with its entrance, arguments, return value(s) ,and exit. Variables: The local variables in each function, and ...


7

The ! denotes writeback of the base register. Base register is the register used to address the memory to be read or written - in your case it's R4. Writeback means that the base register will be updated with the delta equal to the size of transferred data. So, the instruction ldm r4!, {r0, r1, r2, r3} can be represented by the following pseudocode: r0 =...


7

As you need just 2 more bytes, you don't need a large code cave. Out of the box, there are four things you can try: It's very likely you have a function or 2 in your text segment that are present in some source code, but never called. Look for loc_XXXX labels that have the standard function prefix (push ....,LR) and the suffix (pop ....,PC) a few dozen ...


7

I generally try to avoid booting the whole embedded OS when analyzing a target system. Instead, try to run a single target binary with qemu-system-arm -E PATH="/bin:/usr/bin" -E OTHERENVVARS=foo -g 10000 ./myTargetBinary. See slides 27+ in my presentation https://files.sans.org/summit/hackfest2015/PDFs/IoT-Devices-Fall-Like-Backward-Capacitors-Or-the-Month-...


7

So to make an order from the comments - you can do it by using two approaches. Use the original opcodes and write them using wx which stands for "write hex": wx e10b00f9 If you still want to use wa you can do this like this: wa str x1,sp,0x10 In general, handling function's local variables can be done using the afv command and subcommands. Execute afv? ...


6

There are several different calling conventions around on ARM platforms. They vary both according to the processor features (for example, on processors with floating point registers (VFP), it's more efficient to pass floats around in them, but you lose compatibility with processors without VFP) and according to the operating system. A given installation of ...


6

According to documentation the first one is base object destructor and the second one is deleting destructor. Constructors and destructors are simply special cases of <unqualified-name>, where the final <unqualified-name> of a nested name is replaced by one of the following: <ctor-dtor-name> ::= C1 # complete object constructor ...


6

I can think of 2 cases where a VMT is not in the first word of an object: using multiple inheritance when the an object has a member variable which has virtual methods multiple inheritance struct base1 { uint32_t x[12]; virtual void m1() { } }; struct base2 { virtual void m2() { } }; struct cls : base1, base2 { }; now the VMT of base2 is at ...


6

By default, as, uses the old 'divided' syntax for arm and thumb instructions. Hence it is not recognising your pop.w instruction. To make it work, add .syntax unified at the start of your program. This tells it to use the new unified syntax and you should find it assembles pop.w successfully. See https://sourceware.org/binutils/docs-2.24/as/...


6

From http://bear.ces.cwru.edu/eecs_382/ARM7-TDMI-manual-pt2.pdf: E1F322D1 equals 11100001111100110010001011010001 in binary. Your question is specific to the offset, so we can examine the last dozen bits of that binary string with regard to the decomposition rules in the screenshot above: ... Offset 1 SH 1 Offset ... 0010 1 10 1 0001 Thus, the high ...


Only top voted, non community-wiki answers of a minimum length are eligible