Litao3rd · 2015/04/28 joyfully
Another issue of Wargame came, this issue of Wargame is mainly focused on the reverse, basically in GDB to make the idea of the program clear, use some simple infiltration overflow skills, you can succeed. Let’s go!
Again, on the behemoth homepage you’ll find the account and password for the server you logged in to. SSH in and start our journey to Wargame.
level 0
Log on to the server and go to the game folder /behemoth to see all the executable programs you need to run first./ Behemoth0 is the one for this level.
The program asks us to enter a password, presumably to match the password we enter with some fixed password, probably encrypted best match, who knows what it does. GDB to start.
You might see two exciting functions in disassembly code. One is memfrob(), which, as you know by looking for man, does xor between a character in an input string of specified length and the number 42. The other function is STRCMP (), which is the most exciting. As you can see from the flow of the program, the program takes user input from scanf(), does xor through memfrob(), and then sends STRCMP () for matching. So, we just need to break the point at the STRCMP () call. Then look at the stack contents to get the real password.
The password that the program needs to enter is EatMySHORTS, execute the program, and that’s it.
level 1
This procedure is also required to input a password, can not get ready to password, or to GDB go.
Well, looking at the reverse assembly code, it’s simple enough to use gets() to get user input and puts() to print “Authentication failure.\nSorry.” there is no match, that is, no correct password. However, from gets(), which is an insecure function, there is no boundary checking, indicating a buffer overflow vulnerability that can be exploited.
It has been verified that there is a buffer overflow vulnerability. Here is how to exploit this vulnerability, which exploits the previous Wargame a lot.
level 2
The name of the file created is different from that of the pid.
It’s easier to understand the intent of a program by looking at assembly code.
To give an overview of disassembly code, the flow is as follows
#! c id = getpid() s = lstat("touch " + str(id)) if(s & 0xf000 == 0x8000){ unlink(str(id); system("touch " + ID); } sleep(0x7d0); system("cat " + str(id));Copy the code
The program tries to find a file named pid in the current directory, creates the file if it doesn’t exist, performs a long sleep(), and then opens the file again. There are no inputs, no overflows, and no other obvious vulnerabilities. The sleep(a_long_time) function call seems impossible to override, and there is no way to modify.got.plt to try to replace sleep() with another function. Later, referring to similar online writeUp, we found that the relative PATH is used when calling system(). Since it is a relative PATH, we can control this PATH. By modifying the PATH environment variable, we can make the program search the specified PATH first when searching PATH. This allows us to replace the Touch program with the program we want to execute, such as generating a *shell*. That’ll get you through.
Here need to pay attention to the path and fake touch program permissions, I have been failed at the beginning is because of the wrong permissions configuration, wasted a lot of time to press.
level 3
There’s still an input here, and if there’s an input there might be an overflow point.
From the results of the program’s execution, the program printed our input, guessing that there might be a buffer overflow, or a format string vulnerability. After verification, there was a format string vulnerability, so it was very easy, basically without looking at the assembly code.
From the above test, we found that the string storage address is at the sixth offset of the current stack, 0x18(% ESP), which is also visible in GDB. The next step is to construct the attack program. I’m going to put shellcode in an environment variable.
As you can see in the figure above, the environment variable shellCode is stored in 0xFFFFD78C, which may be a little bit off, but we have a Nop SLED, a Return Address that holds the program’s original Return Address, which we need to change to ShellCode
Cat is performed here to prevent the pipe from closing, as was done earlier in Wargame. One thing to note is that on the right side of the pipe, I used a relative path at the beginning, which always failed to get the correct result, and I didn’t know where the problem was. Later, I accidentally used an absolute path to solve the problem. I don’t know why. I will take notes after I see the concrete principle of the pipe.
level 4
PID not found! , it seems that the program is related to PID again.
From the disassembly out of the code can roughly understand the implementation process of the program.
The program opens/TMP /pid, then sleeps (1) for a second, then outputs the contents of the file, so we simply soft link the file to the password file, then we can tell the program to open the password file and output the contents of the file. The difficulty is, how do we know the PID of a program? Although the PID is incremented under Linux, there is no guarantee that it is incremented by one unit at a time. So, I thought of an inelegant way, we first create a large number of possible PID soft link files, and then keep executing the program, the pid of the execution program will fall within the scope of the file we created.
behemoth4.py
#! python #! /usr/bin/env python #coding=utf-8 import sys, os passwd_file = "/etc/behemoth_pass/behemoth5" if len(sys.argv) < 2: print "usage %s [start pid num]" sys.exit(-1) try: start_pid = int(sys.argv[1]) except ValueError: Print "usage %s [start pid num]" sys.exit(-1) # print "usage %s [start pid num]" sys.exit(-1) # Os.popen ("ln -s "+ passwd_file +"/TMP /" + STR (I +start_pid)) # ret = os.popen("/behemoth/behemoth4") ret = ret.read() if not "not" in ret: Print ret break # for I in range(50): os.popen("rm/TMP /" + STR (I +start_pid))Copy the code
Getting the pid of the child process in Python is too much trouble, otherwise the blasting code could be written more elegantly. But it doesn’t affect the results. It still pops out. It is important to note that the start PID parameter of the program should be selected a little larger, because the symbolic link file in the program starts many child processes. I have added 500 numbers on the basis of the original, otherwise it is easy to cross.
level 5
This close execution program has no output, no prompt, or directly look at the disassembly out of the code. code
As you can see, the program opens the password file /etc/behemoth_pass/behemoth6, sets up the socket localhost:1337, and sendto to send the contents of the file. The flow of the program is obvious, then we just listen to local port 1337 can receive the password. Note that sendto is sent using UDP. You need to listen for UDP packets on this port.
Use the Swiss Army knife NC to listen, and then execute the program in another shell, NC will output the received UDP packet content.
shell 1
shell 2
shell 1
level 6
There are two executables in this level, neither of which yields any meaningful results, so let’s go straight to the disassembled code.
The first main program establishes a pipe with the second program /behemoth/behemoth6_reader and reads through the pipe. If it reads something equal to HelloKitty, it executes execl() to create a shell. Let’s look at the second program. The second program will output “Couldn’t open shellcode.txt”. Create a file called shellcode.txt.
The program first opens a file named shellcode. TXT, and then reads the contents of the file to the dynamic storage area, and finally jumps to the dynamic storage area to execute the contents read. In shellcode.txt, we store a piece of shellcode. This piece of shellcode performs only one task, which is to print a string HelloKitty to stdout.
section .text
global _start
_start:
mov ax, 0x7974 ; ty
movzx eax, ax ; zero-extend ax to 32bits
push eax
push 0x74694b6f ; oKit
push 0x6c6c6548 ; Hell
mov ecx, esp
xor ebx, ebx
inc ebx
xor edx, edx
mov dl, 10
xor eax, eax
mov al, 4
int 80h
; exit(0)
xor ebx, ebx
xor eax, eax
mov al, 1
int 80h
Copy the code
Above is the shellcode I wrote output HelloKitty program, after assembly can get the available shellcode program. Note that the Behemoth6_reader program also uses a relative path, and since it’s a relative path, it’s something we can control. Create the behemoth6 folder under/TMP and set the current folder to/TMP /behemoth6 and operate from there.
level 7
This level of the program is also executed without any output, so said this wargame is mainly to see the reverse ability, basically can reverse out of the program flow, the problems behind are very easy to solve. Assembly out of the program is very long, will not stick.
isspace(), isalpha(), isspace(), isalpha(), etc. That is, similar tests are performed in the program, plus the conclusion from the rest of the code as a whole. The program checks for non-alpha characters in argv[1], which is probably Shellcode, and prompts an error. As the picture shows,
As shown in the figure above, when argv[1] is executed for the first time, there is a character in argv[1], and the program reports an error indicating that shellCode may exist.
However, the program only detects the first 256 characters in argv[1], so we only need to fill the first 256 with alpha characters for buffer overflow. But the program cleaned out all of the environment variables, which meant we couldn’t put ShellCode in the environment variables, we had to find somewhere else to put shellCode, and at the beginning, I put shellCode at the end of argv[1], with a Nop sled, An Illegal Struction is used to execute the stack. I ended up using return-to-libc, changing the return address to the address of the system() function, and placing the /bin/sh argument in argv[2] with some gueswork.
end of the game
I have completed another phase of Wargame, now the difficulty is not very big, it is some very basic reverse, overflow knowledge, but as a novice, I deeply know that laying a good foundation is the most important, there are still a lot of fun behind. Please look forward to it
To learn more about Wargame, check it out here!