That’s an easy one. The first parameter of read is decided by the first argument (which is up to our choice).
The first parameter refers to the file descriptor.
When it is 0, it refers to STDIN.
Therefore, all we need to do is to make sure the first parameter is 0, and supply the string for comparison.
Payload
collision
Daddy told me about cool MD5 hash collision today.
I wanna do something like that too!
ssh col@pwnable.kr -p2222 (pw:guest)
The source code is provided:
It basically waits for a string of length 20 supplied as the first argument.
Then it interprets it as 5 int32 values, and checks whether the sum is equal to the hash. We can first print a bunch of \x01’s and calculate what the last int32 should be. Note that it’s little-endian.
Payload
bof
Nana told me that buffer overflow is one of the most common software vulnerability.
Is that true?
nc pwnable.kr 9000
Let’s see the assembly of func:
The difference between the address of the string of the input and the argument, key, is 0x2c + 0x8.
Payload
Note that we need the weird cat <() - so that the pipe won’t close STDIN for our further access to the shell.
flag
Papa brought me a packed present! let’s open it.
This is reversing task. all you need is binary
Download : http://pwnable.kr/bin/flag
Let’s see if there is any raw string that is intriguing.
Now we know it’s packed, let’s decompress it with upx -d.
After that, let’s read the assembly:
And yeah, the flag is there…
passcode
Mommy told me to make a passcode based login system.
My initial C code was compiled without any error!
Well, there was some compiler warning, but who cares about that?
ssh passcode@pwnable.kr -p2222 (pw:guest)
We have the source:
We can immediately see that this is a problem:
From the layout of the variables, we can see that we might be able to control the variables by inserting appropriate values during welcome().
And there we can see, the dword after the first 0x60 bytes of the name will decide the value in password1. However, since we are only allowed to write 100 bytes, and 0x60 + sizeof(dowrd) = 100, we can’t do the same thing for password2. So let’s see what we can do when password1 is under our control.
The scanf in the context allows us to write an arbitrary dword through STDIN to any address (of which should be written into passcode1). Then there is a function call to fflush. The address to glibc function calls are resolved by a table called GOT, and we can exploit the scanf to help us modify that table so that the resolved address of fflush points to the address of our choice.
This tells us the address we want to modify is 0x0804a004.
And this tells us 0x080485e3~0x080485ea gives us the flag.
Payload
random
Daddy, teach me how to use random value in programming!
ssh random@pwnable.kr -p2222 (pw:guest)
Here’s the source:
Since there is no random seed, we need only to find out what’s the first random value. An easy way to do that is to write a fairly short code and run it.
Then run ./random and provide the value 0xdeadbeef ^ 1804289383 in integer, which happens to be 3039230856.
input
Mom? how can I pass my input to a computer program?
ssh input2@pwnable.kr -p2222 (pw:guest)
Here’s the source:
Let’s solve this with C, as I am more familar with UNIX programming in C.
argv
What we want here is 100 arguments, the ‘A’‘th of which is “\x00”, and the ‘B’‘th of which is “\x20\x0a\x0d”. We can do that by passing the appropriate argument list to execve().
stdio
We need file descriptor 0 (typically STDIN) to have “\x00\x0a\x00\xff”, and 2 (typically STDERR) to have “\x00\x0a\x02\xff”. Since we need our program to direct its output to the screen, and it’s better if we could just pass the strings in the program, we’d fork a child process and run ./input there so that the parent process could simply write to the required file descriptors.
The steps are:
Create two pipes, one for STDIN and the other for STDERR.
Fork a child process to run ./input. In the child process, its STDIN and STDERR is mapped to the pipes created in the previous step.
The parent process will write the required strings through the pipes.
envp
We need to set the environment variable. That’s as easy as setting argv.
file
We could have also created that file with bash, but we can do that as well in C.
network
We need to launch a client and connect with the server on ./input, through the port decided by argv[‘C’] (which is of our choice). Then we are asked to send the required string.
We could just copy most of what’s there for running the server.
Note that we can’t run our program in the directory with the flag. However, we need to have the flag in the current directory in order to see the flag called by system(“/bin/cat flag”). To resolve this issue, we can simply create a symbolic link in the current directory.
Payload
leg
Daddy told me I should study arm.
But I prefer to study my leg!
Download : http://pwnable.kr/bin/leg.c
Download : http://pwnable.kr/bin/leg.asm
ssh leg@pwnable.kr -p2222 (pw:guest)
We have the source:
If we know the return value of key1(), key2(), and key3(), we’ll get the flag.
In ARM, $pc points to the current address + 8. The return value of key1() is thus 0x8ce4.
Notice how the length of the instructions are different? The command bx stands for “branch and exchange instruction set”. It will jump to the address in the operand and switch the instruction to either ARM or THUMB, depending on the LSB of the address. The return value of key2() is 0x8d0c.
lr refers to the return address from the function, that’s the address of the instruction right after the call, which is 0x8d80.
So the answer is 0x8ce4 + 0x8d0c + 0x8d80 = 108400
mistake
We all make mistakes, let’s move on.
hint : operator priority
ssh mistake@pwnable.kr -p2222 (pw:guest)
The source:
Let’s see what it does in the beginning.
As long as “/home/mistake/password” is readable, open() will return a non-negative value, and thus fd will be 0 (false). The file descriptor, 0, refers to STDIN. That makes the following read() take a string of length 10 from STDIN to pw_buf[]. Then, every byte is xored by 1, and compared with another string of length 10 fed in to STDIN.
So, just prepare two adjacent characters on the ASCII table (works 50%), each repeated 10 times.
Payload
shellshock
Mommy, there was a shocking news about bash.
I bet you already know, but lets just make it sure :)
ssh shellshock@pwnable.kr -p2222 (pw:guest)
The source:
As the name of the challenge suggests, it’s the vulnerability in bash that was discovered in 2014.
When bash executes something, it loads environment variables. However, the bug was that if an environment variable was a function definition, whatever follows it is executed :P
Payload
coin1
Mommy, I wanna play a game!
Running at : nc pwnable.kr 9007
This is what you will see:
We can simply do a binary search… The problem is, the connection is too slow to pass this in time. So we’d better run the script in the server. Here I am using python because it’s the only language with pwnlib installed on the server…
Payload
blackjack
Hey! check out this C implementation of blackjack game!
I found it online
I like to give my flags to millionares.
how much money you got?
Running at : nc pwnable.kr 9009
We are interested in how the money variable is modifed during the games. The following is the logic of how the cash is determined after a loss.
And this is the logic of how the variable “bet” is determined.
The only restriction on “bet” is that it can’t be greater than “cash”, thus we can simply put a negative number so that when we lose, we would instead receive that amount of money.
Payload
lotto
Mommy! I made a lotto program for my homework.
do you want to play?
ssh lotto@pwnable.kr -p2222
The source:
First, we can see that the password is decided by random (range [1, 45]):
Next, the comparison is pairwise:
That means, “match” can be any value in [0, 36]. In order to get the flag, we have to have match exactly 6. One feasible way is to feed in 6 same characters in the range. This way, if that character appears in the randomly generated 6 bytes exactly once, the match will be 6. The odds turns out be: \(\frac{6\times44^5}{45^6} = 0.12\).
Payload
cmd1
Mommy! what is PATH environment in Linux?
ssh cmd1@pwnable.kr -p2222 (pw:guest)
The source:
It executes the first argument, as long as it doesn’t contain any of “flag”, “sh”, and “tmp”. The PATH is set to some weird place, so we need to call what we need with absolute path.
Payload
cmd2
Daddy bought me a system command shell.
but he put some filters to prevent me from playing with it without his permission…
but I wanna play anytime I want!
ssh cmd2@pwnable.kr -p2222 (pw:flag of cmd1)
The source:
This time we can’t have ‘/’ in our command, and utilities we need for reading the flag are not in the path.
However, there are some commands and keywords that are builtin, and is accessible regardless of the PATH. For example, “continue”, “break”, “cd”, and so on. One of them, “command”, has the capibility of finding standard utilities when the flag “-p” is on.