Android ARM 32-bit
0x00
This article only explains how to learn Android ARM 32-bit by step. Readers should read this article first, and then read this article when encountering problems.
0x01
The first question: payload = 'A' * 132 + p32 (callsystemaddr), how does this 132 come from?
To answer this question, we need to disassemble level6.c. The level6.c code is as follows:
#include
#include
#include
void callsystem(){system("/system/bin/sh");} void vulnerable_function() {char buf[128];read(STDIN_FILENO, buf, 256);} int main(int argc, char** argv) {if (argc==2&&strcmp("passwd",argv[1])==0)callsystem();write(STDOUT_FILENO, "Hello, World\n", 13); vulnerable_function();}
After compiling with ndk-build, we drag the level6 generated into ida pro and find the disassembly code corresponding to vulnerable_function:
.text:00008564 sub_8564.text:00008564 PUSH {LR}.text:00008566 MOVS R2, #0x80.text:00008568 SUB SP, SP, #0x84.text:0000856A MOV R1, SP.text:0000856C LSLS R2, R2, #1.text:0000856E MOVS R0, #0.text:00008570 BL sub_9414.text:00008574 ADD SP, SP, #0x84.text:00008576 POP {PC}.text:00008576 ; End of function sub_8564
Refer to the rules for inserting parameters in the ARM sub-function definition into registers. This function corresponds to the following function code:
void vulnerable_function() {char buf[128];read(STDIN_FILENO, buf, 256);}
R0 corresponds to STDIN_FILENO, buf corresponds to SP-0X84, R2 corresponds to 256, the parameter has been stored in the register, then BL sub_9414 is to call the read function. So how did 132 come from? Let's look at a figure:
The next address is LR, that is, the return address. If this address is overwritten, the corresponding function is executed.
0x02
Callsystemaddr = 0x00008554 + 1. This address is the static address of callsystem in ida during static analysis. After level is loaded and executed in the memory, is the corresponding virtual address still the same? The answer is this address. We can use cat/proc/pid/maps to observe the ing table. For example:
0x03
Payload = '\ x00' * 132 + p32 (gadget1) +' \ x00' * 0xc + p32 (r0) + '\ x00' * 0x4 + p32 (gadget2) + p32 (r1) + p32 (r2) + p32 (r4) + p32 (r5) + p32 (r6) + p32 (write_addr_plt) + '\ x00' * 0x84 + p32 (ret_to_vul). Why does' \ x00' * 0x84 + p32 (ret_to_vul) return to the vulnerable_function function?
The answer is that gadget2 is the write function. When the write function is executed, the LR is first pushed into the stack. At this time, the LR still points. text: 00008574 add sp, SP, #0x84. Because only BL sub_9414 is executed, the address of the next row is stored in LR, which remains unchanged.
After the write function is executed, pop {pc} continues. text: 00008574 code, that is, the two sentences of code. text: 00008574 add sp, SP, #0x84. text: 00008576 POP {PC}, so that you can understand why the vulnerable_function can be returned by writing '\ x00' * 0x84 + p32 (ret_to_vul.