3

My Friend recently completed a hacking challenge and sent it to me (binary and source). I wanted to ask here before I asked him for tips as I want to do it myself :)

I've been going through it but I am struggling to find the vulnerability.

#include <alloca.h> #include <stdio.h> #include <string.h> #include <stdlib.h> static void usage(const char *argv0) { printf("Build your own string!\n"); printf("\n"); printf("Usage:\n"); printf(" %s length command...\n", argv0); printf("\n"); printf("Each command consist of a single character followed by it's index.\n"); printf("\n"); printf("Example:\n"); printf(" %s 11 h0 e1 l2 l3 o4 w6 o7 r8 l9 d10\n", argv0); exit(1); } int main(int argc, char **argv) { char *buffer; unsigned short buffersize, i, index, length; if (argc < 2) usage(argv[0]); length = atoi(argv[1]); if (length <= 0) { fprintf(stderr, "bad length\n"); return 1; } buffersize = length + 1; buffer = alloca(buffersize); memset(buffer, ' ', buffersize); buffer[buffersize - 1] = 0; for (i = 2; i < argc; i++) { if (strlen(argv[i]) < 2) { fprintf(stderr, "bad command \"%s\"\n", argv[i]); return 1; } index = atoi(argv[i] + 1); if (index >= length) { fprintf(stderr, "bad index in command \"%s\"\n", argv[i]); return 1; } buffer[index] = argv[i][0]; } printf("%s\n", buffer); return 0; } 

I think the vulnerability lies within the short int, and the use of alloca.

Entering ./app 65535 65535 can cause a segfault but I can't actually override anything since buffer will only ever be set to max 65535 or it loops around. This makes me think I can't override the EIP to inject shellcode.

Can anyone help me with where to look at?

Thanks!

5
  • Try inputting the number defined as USHRT_MAX in your environment for the first argument, Commented Feb 27, 2016 at 15:06
  • @MikeCAT Yeah I tried that, I can get a seg fault but cant override anything of value since the int will just loop around if I set it larger than the max. Commented Feb 27, 2016 at 15:12
  • @JDoby, how will you get a segmentation-fault? Commented Feb 27, 2016 at 15:12
  • Debugger should be useful to see where the variables and return address are located, and what is the value in buffer. Commented Feb 27, 2016 at 15:15
  • since buffersize and length are unsigned int: setting length to 65535 will cause buffersize to be 0, so nothing will be allocated on the stack for buffer. However, since index is compared to length, buffer[index] can be used to override the first 64Kb of the stack. Commented Feb 27, 2016 at 15:26

1 Answer 1

5

Actually, the vulnerability lies in the fact that you can store a character at any offset in the buffer allocated with alloca, but the test is done on length rather than size. passing arguments of 65535 and a1 invokes undefined behavior: size as value 0 because of arithmetic wraparound if unsigned short has 16 bits.

You can try passing a first argument of 65535 and subsequent arguments with increasing offsets, that will poke values beyond the end of buffer, possibly overwriting the return address of main and causing a crash:

myprog 65535 a3 a7 a15 a19 a23 a27 a31 a35 a39 a43 a47 a51 a55 a59 a63 ... 

Depending on the actual local variable layout, the required offset may be larger than 17, but should be smaller than 80.

Sign up to request clarification or add additional context in comments.

2 Comments

Awesome, I actually tried this but didn't enter enough to actually cause a crash! How would I go about entering 'A's for this to override EIP with x414141 as I can only seem to enter offset numbers like you said.
@JDoby: you would first locate the return address, say 24 and then pass arguments A24 A25 A26 A27... 4 or 8 of them depending on the architecture. But a single poke into a more significant byte of the return address should suffice, and would be more elegant.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.