↪ file applestore applestore: ELF 32-bit LSB executable, Intel i386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=35f3890fc458c22154fbc1d65e9108a6c8738111, not stripped
checksec
1 2 3
↪ checksec --file=applestore RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH 91 Symbols No 0 4 applestore
./applestore
1 2 3 4 5 6 7 8 9
↪ ./applestore === Menu === 1: Apple Store 2: Add into your shopping cart 3: Remove from your shopping cart 4: List your shopping cart 5: Checkout 6: Exit >
When you add an item, they will create a chunk of 16 bytes on heap, assume address of this chunk is v, v + 0 would store name of the item, v + 4 stores price of the item, and v + 8 stores the next item, v + 12 stores the previous item (this is for the linked list). Then, this chunk will be inserted into a doubly linked-list, and the head will be stored at 0x804B070. Delete function allows you to remove an item and delete the chunk from the linked-list. Cart function lists all items and calculates the total price. Finally, checkout function prints the total price and if the total price is 7174, they will gift you an Iphone 8 for 1 dollar. And now, notice that in cart, delete and handler, they allow us to input 21 bytes for the numbers, representing the option, resulting to vulnerability.
0x4. Exploit
When the total price is 7174, they add Iphone 8 to your cart, but they don’t use create funtion to do that, instead they use spaces on stack and add it to linked-list. And because the stack frame of delete and checkout is at the same address (ebp of these two functions is the same). As I said above, we can input 21 bytes for v6 (at ebp - 0x22 ) in delete function and Iphone 8 would be stored at ebp - 0x20. As a result, we can manipulate the tail of the linked-list. To reach 7174 in total price, you could buy 6 Iphone 6 and 20 Iphone 6 plus or whatever:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#include<bits/stdc++.h> usingnamespace std;
intmain() { int r, q, k; for (int d = 0; d * 499 <= 7174; ++d){ r = 7174 - 499 * d; for (int c = 0; 399 * c <= r; ++c){ q = r - 399 * c; for (int b = 0; 299 * b <= q; ++b){ k = q - 299 * b; if (k % 199 == 0){ cout << k / 199 << ' ' << b << ' ' << c << ' ' << d << '\n'; } } } } }
After add Iphone 8 to your linked-list, this tail will start from ebp-0x20 and when you call delete function, you can input 21 bytes from ebp-0x22. The first two bytes are for the index you want to remove, the next 16 bytes are spaces of this tail.
1
printf("Remove %d:%s from your shopping cart.\n", v1, *(const char **)v2);
And as you can see after removed, they will print the value at address stored at v2, and in our case, they will print the address’s value at ebp - 0x20.
1 2 3 4 5 6 7
ebp-0x22 -> 27 ebp-0x20 -> the address you want to leak ebp-0x1c -> (the price of product) ebp-0x18 -> (the next item) c ebp-0x14 -> (the previous item) d ... ebp
Now, you can get the libc base, so what next ?
After removing an element from linkedlist, they merge 2 segments like this:
So, what if I remove Iphone 8 from linked-list. Assume what’s in ebp-0x18 is c and ebp-0x14 is d. they will do this:
1 2
*(d + 8) = c *(c + 12) = d
If we overwrite address of atoi at GOT + 0x22 to ebp-0x18 and ebp-8 to ebp-0x14, after leave instruction (means esp = ebp + 4, ebp = [ebp]), we can make ebp points to the address of atoi at GOT + 0x22. You can get the address of stack leaked from environ in libc, and then calculate the ebp of delete function.
And now using my_read in handler you can overwrite address pointed by (ebp-0x22), in this case, it’s atoi’s GOT address.Overwrite system address and ‘;sh;’ to it, then you can get the shell.