Too many of us today want instant gratification.... We want reward without work. We want the thinking done for us. We want to understand something right away or we can't be bothered. This attitude demeans the accomplishments of those who are true masters. | |
P. T. Sudo |
OK. Time to withdraw and assess our position. At this point the enemy has the advantage, they have all the trumps, by suitably stealthing the binary they have managed to hide it's purpose and also remove the ability to debug the binary using the techniques we had known. A summary of our position was in order. We had a binary in our possession that displayed properties of a trojan, and appeared to have been part of a rootkit because it had been compiled on an old system, and probably one which a skilled cracker wouldn't use. When executed, wtfu4 immediately forked twice and formed a listening process under the name [mingetty] bound to port 11. Uhhhmmm. Very good, but it doesn't answer any of the questions posed. We can guess at it's capabilities at this point, but we have no proof of what it does. We guessed it was a DDOS tool. We needed some way of seeing the structure of wtfu4 so we could make some educated guesses as to where we should be looking for the control sections.
Fresh from the turmoil of 3 hours chasing our tails we stepped back and had a logical look at the facts discussed above. There was nothing else for it, we had to disassemble the wtfu4 binary and attempt to reconstruct its call stack. Maybe gdb will help us step through the program flow? Nope, that doesn't like forks from the limited commandline experience we have had with it coding C we couldn't get it to do anything useful. Another area for revision. This is getting too much. We decide to try our friend Google again. This time we are researching +"Reverse Engineering" + "ELF binaries". We get a few hits of some interesting papers, but nothing of worth. Hold on, a Phrack article, that will go much deeper than we need, but should be helpful. It was at this point we hit rock bottom when we read the opening paragraph of this article.
"The Unix world has lagged far behind the Microsoft world (including both MS-DOS and MS-Windows) in the twin realms of binary protection and reverse engineering."
What followed was a near 10 hour long investigation into the processes and tools of ELF binary reverse engineering. We got a disassembled version of the file quite early using objdump another part of the standard Linux toolkit on a developer's build. We quickly concluded after looking at the disassembled output that this was the work of someone of advanced skills, there was absolutely nothing to give away clues as to the function of wtfu4 - hence the affectionate nickname. Never-the-less, onward we trudged. At this point it was like walking up the side of Mount Everest in the coldest part of the year with a 5,000lb rucksack . It was hard work. We had no assembler skills even to read the disassembly, let alone debug it. The next stage was the most difficult, and most time consuming, we had to develop the skills to decipher the disassembled output and attempt to locate the decoding function. Included is the annotated disassembly output from rec +strings +showloops wtfu4/misc/the-binary.rec. It was painful. We quickly identified the close (0), close(1) of the original strace output, but we were struggling to make much sense of the rest of it. One of the biggest problems was identifying where the socket recv call was taking place. The other was that it was very difficult to assemble any structure to the execution of this binary when we didn't know assembly. We spent several hours trying to make sense of it.
To get the disassembled code for the binary we used objdump as follows.
[root@WhiteHat root]# objdump -D ./original > binary.asm
This gave us a very good basis for the continued analysis of the binary, but we still had a steep learning curve to understand even half of what was going on here. Give us something resembling C and we might stand a chance, but from this... it's going to take weeks.
We could however, annotate some of this assembly output where we could identify the close() commands from the strace output. An annotated disassembled output is contained in the additional file archive for reference, but the section of interest is shown below.
Possible reference to string: "/" 0x0804820c push $0x80675e3 push "/" onto stack. 0x08048211 call 0x08057134 chdir("/") call. 0x08048216 push $0x0 0x08048218 call 0x08057160 CLOSE(0) 0x0804821d push $0x1 0x0804821f call 0x08057160 close(1) 0x08048224 push $0x2 0x08048226 call 0x08057160 close(2) 0x0804822b movl $0x0,0x807e774 0x08048235 movl $0x0,0x807e770 0x0804823f movl $0x0,0x807e778 0x08048249 push $0x0 0x0804824b call 0x08057444 time(NULL) 0x08048250 add $0x14,%esp 0x08048253 push %eax 0x08048254 call 0x080559a0 0x08048259 add $0x4,%esp 0x0804825c push $0xb 0x0804825e push $0x3 0x08048260 push $0x2 0x08048262 call 0x08056cf4 socket(PF_INET, SOCK_RAW, 11) 0x08048267 mov %eax,0xffffbb38(%ebp) 0x0804826d push $0x1 0x0804826f push $0x1 0x08048271 call 0x080569bc # ? 2 params (1,1) - SIGHUP
We can see that the output from the disassembly can now be matched up to the output from strace. For those interested, the full disassembly is included in the additional files wtfu4/misc/the-binary.rec
So we now had somewhere to start. The next section of disassembly meant absolutely nothing to us. Remember, we weren't assembly programmers so we were beginning to struggle a little. The next section of the disassembly is shown below with our annotations on. These annotations were added later.
Referenced from jump at 08048ec5 (U); 0x080482b0 push $0x0 # flags = 0 0x080482b2 push $0x800 # buffer = 2048 0x080482b7 lea 0xfffff800(%ebp),%eax # length buffer? 0x080482bd push %eax 0x080482be mov 0xffffbb38(%ebp),%ecx # ptr -> buffer? 0x080482c4 push %ecx 0x080482c5 call 0x08056b44 # wait for input 0x080482ca mov %eax,%esi # we have input on the socket. 0x080482cc add $0x10,%esp 0x080482cf mov 0xffffbb30(%ebp),%edx # save length of buffer in edx 0x080482d5 cmpb $0xb,0x9(%edx) 0x080482d9 jne 0x08048eb8 0x080482df mov 0xffffbb2c(%ebp),%ecx 0x080482e5 cmpb $0x2,(%ecx) # cmp (byte) %ebp to 2 (dec) result - ecx make ecx current. 0x080482e8 jne 0x08048eb8 # if <> 2 jump. 0x080482ee cmp $0xc8,%esi # cmp %ecx to 200 (dec) result to esi 0x080482f4 jle 0x08048eb8 # if <= 200 jump 0x080482fa mov 0xffffbb20(%ebp),%edx # 0x08048300 push %edx # 0x08048301 mov 0xffffbb28(%ebp),%ecx #