/******************************************************************************* * * xcte.c - Extract Chunked Transfer-Encoding from TCP stream files * * Copyright (C) 2010 - Christian North * *******************************************************************************/ #include #include #include #define version "v0.2 BETA" /******************************************************************************/ void usage() { printf("XCTE %s - ",version); printf("Extract Chunked Transfer-Encoding from TCP stream files\n"); printf("Usage: xcte \n"); exit(0); } /******************************************************************************/ int chunked_encoding(FILE *stream) { const char *encoding="Transfer-Encoding: chunked"; size_t len=1024; char data[len]; long offset=0; int bytes=0; int c=0; while(!feof(stream)){ if((bytes=fread(data,1,len,stream)) == 0) break; for(c=0;c<(bytes-1);c++){ if(data[c] == 0x0D && data[c+1] == 0x0A){ data[c]='\0'; offset+=strlen(data)+2; break; } } if(strstr(data,encoding) != NULL) { rewind(stream); return 1; } fseek(stream,offset,SEEK_SET); } return 0; } /******************************************************************************/ FILE *disposition(char *data) { const char *disposition = "Content-Disposition"; const char *filename = "filename="; FILE *fp = NULL; if(strstr(data,disposition) != NULL) { filename=strtok(data,"="); printf("Extracting Content: "); printf("%s\n",data+strlen(filename)+1); fp=fopen(data+strlen(filename)+1,"a"); return fp; } return NULL; } /******************************************************************************/ int extract(FILE *stream, FILE *content) { size_t chunk=0; size_t len=8; char *fragment; char data[len]; char hex[len]; while(!feof(stream)){ if(fread(data,1,len,stream) == 0) break; snprintf(hex,len,"%c%c%c%c",data[2],data[3],data[4],data[5]); chunk=strtoul(hex,NULL,16); if((fragment = malloc(chunk)) == NULL) break; if(fread(fragment,1,chunk,stream) == 0) break; fwrite(fragment,1,chunk,content); free(fragment); } fclose(content); return 0; } /******************************************************************************/ int main(int argc, char **argv) { char *streamfile=NULL; FILE *stream=NULL; FILE *content=NULL; size_t len=1024; char data[len]; long offset=0; int bytes=0; int c=0; if(argc != 2) usage(); streamfile = argv[1]; if((stream = fopen(streamfile,"r")) == NULL) usage(); if(!chunked_encoding(stream)){ printf("Transfer-Encoding: chunked - not found in "); printf("\"%s\"\n", streamfile); exit(0); } while(!feof(stream)){ if((bytes=fread(data,1,len,stream)) == 0) break; for(c=0;c<(bytes-1);c++){ if(data[c] == 0x0D && data[c+1] == 0x0A) { data[c]='\0'; offset++; break; } offset++; } content = disposition(data); if(content != NULL) break; fseek(stream,offset,SEEK_SET); } offset--; fseek(stream,offset,SEEK_SET); while(!feof(stream)){ if((bytes=fread(data,1,len,stream)) == 0) break; for(c=0;c<(bytes-4);c++){ if(data[c] == 0x0D && data[c+1] == 0x0A && data[c+2] == 0x0D && data[c+3] == 0x0A ){ offset+=2; fseek(stream,offset,SEEK_SET); extract(stream,content); fclose(stream); break; } offset++; } } return 0; } /******************************************************************************/ After compiling this with "gcc -o xcte xcte.c" I was able to extract the executables contained in both stream files that had references to "file.exe" $ gcc -o xcte xcte.c $ ./xcte C0A81781-1066-3B355B66-80 Extracting Content: file.exe $ file file.exe file.exe: PE32 executable for MS Windows (GUI) Intel 80386 32-bit $ md5sum file.exe 5942ba36cf732097479c51986eee91ed file.exe $ rm file.exe $ ./xcte C0A81781-1067-3B355B66-80 Extracting Content: file.exe $ file file.exe file.exe: PE32 executable for MS Windows (GUI) Intel 80386 32-bit $ md5sum file.exe 5942ba36cf732097479c51986eee91ed file.exe The tail end of the checksum matches the hint for question #4. =============================================================================== Q4. As part of the infection, a malicious Windows executable file was downloaded onto Ms. Moneymany’s system. What was the file’s MD5 hash? Hint: It ends on -Y΄91ed‘. A4. 5942ba36cf732097479c51986eee91ed =============================================================================== Unfortunatelly I don't have a lot of experience with malware or packers so I turned to google and found a list of candidates. Using hexdump against the executable file suggested the packer was UPX. $ hexdump -C -n 1024 file.exe 00000000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 |MZ..............| 00000010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........@.......| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 e8 00 00 00 |................| 00000040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 |........!..L.!Th| 00000050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f |is program canno| 00000060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 |t be run in DOS | 00000070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 |mode....$.......| 00000080 2b 97 33 0a 6f f6 5d 59 6f f6 5d 59 6f f6 5d 59 |+.3.o.]Yo.]Yo.]Y| 00000090 ac f9 00 59 67 f6 5d 59 48 30 30 59 6d f6 5d 59 |...Yg.]YH00Ym.]Y| 000000a0 6f f6 5c 59 2c f6 5d 59 36 d5 4e 59 6c f6 5d 59 |o.\Y,.]Y6.NYl.]Y| 000000b0 48 30 33 59 67 f6 5d 59 48 30 27 59 6e f6 5d 59 |H03Yg.]YH0'Yn.]Y| 000000c0 48 30 21 59 6e f6 5d 59 48 30 25 59 6e f6 5d 59 |H0!Yn.]YH0%Yn.]Y| 000000d0 52 69 63 68 6f f6 5d 59 00 00 00 00 00 00 00 00 |Richo.]Y........| 000000e0 00 00 00 00 00 00 00 00 50 45 00 00 4c 01 03 00 |........PE..L...| 000000f0 96 25 99 4b 00 00 00 00 00 00 00 00 e0 00 03 01 |.%.K............| 00000100 0b 01 08 00 00 10 01 00 00 10 00 00 00 80 00 00 |................| 00000110 30 8f 01 00 00 90 00 00 00 a0 01 00 00 00 40 00 |0.............@.| 00000120 00 10 00 00 00 02 00 00 04 00 00 00 00 00 00 00 |................| 00000130 04 00 00 00 00 00 00 00 00 b0 01 00 00 10 00 00 |................| 00000140 00 00 00 00 02 00 00 04 00 00 10 00 00 10 00 00 |................| 00000150 00 00 10 00 00 10 00 00 00 00 00 00 10 00 00 00 |................| 00000160 c4 a2 01 00 78 00 00 00 84 a1 01 00 40 01 00 00 |....x.......@...| 00000170 00 a0 01 00 84 01 00 00 00 00 00 00 00 00 00 00 |................| 00000180 00 00 00 00 00 00 00 00 3c a3 01 00 0c 00 00 00 |........<.......| 00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000001e0 55 50 58 30 00 00 00 00 00 80 00 00 00 10 00 00 |UPX0............| 000001f0 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 |................| 00000200 00 00 00 00 80 00 00 e0 55 50 58 31 00 00 00 00 |........UPX1....| 00000210 00 10 01 00 00 90 00 00 00 02 01 00 00 04 00 00 |................| 00000220 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 e0 |............@...| 00000230 2e 72 73 72 63 00 00 00 00 10 00 00 00 a0 01 00 |.rsrc...........| 00000240 00 04 00 00 00 06 01 00 00 00 00 00 00 00 00 00 |................| 00000250 00 00 00 00 40 00 00 c0 00 00 00 00 00 00 00 00 |....@...........| 00000260 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000003d0 00 00 00 00 00 00 00 00 00 00 00 33 2e 30 34 00 |...........3.04.| 000003e0 55 50 58 21 0d 09 02 0a 48 ae 9d 34 9e c6 c6 02 |UPX!....H..4....| 000003f0 04 65 01 00 27 ff 00 00 00 42 01 00 26 02 00 2e |.e..'....B..&...| 00000400 =============================================================================== Q5. What is the name of the packer used to protect the malicious Windows executable? Hint: This is one of the most popular freely-available packers seen in ΄mainstream‘ malware. A5. UPX =============================================================================== To answer question #6 I downloaded a copy of UPX and used it to decompress the executable "file.exe." $ upx -d file.exe Ultimate Packer for eXecutables Copyright (C) 1996 - 2009 UPX 3.04 Markus Oberhumer, Laszlo Molnar & John Reiser Sep 27th 2009 File size Ratio Format Name -------------------- ------ ----------- ----------- 82432 <- 68096 82.61% win32/pe file.exe Unpacked 1 file. $ md5sum file.exe 0f37839f48f7fc77e6d50e14657fb96e file.exe =============================================================================== Q6. What is the MD5 hash of the unpacked version of the malicious Windows executable file? A6. 0f37839f48f7fc77e6d50e14657fb96e =============================================================================== To find the last answer I needed to infect a Windows XP host and monitor where it tries to connect on the Internet. VMWare proved to be an excellent tool for this task. I have an ESX server in my home lab that I used to create a new resource pool called "forensics". In this resource pool I created 2 virtual machines. One running linux with a Apache and a copy of my IP traffic analyzer. The other running Windows XP. These systems where isoloated from the Internet but connected to each other. The Linux host was configured as the gateway for the Windows system. Next I placed a copy of file.exe in the the default web root of the Linux server running Apache. On the Windows host I downloaded file.exe from the Linux server using a web browser. Then I started my IP traffic analyzer on the Linux host to monitor all network communications from the Windows host. On the Windows host I opened "file.exe" and monitored the output of the traffic analyzer on the Linux machine. Immediately a connection attempt was made to 213.155.29.144 on TCP/444. =============================================================================== Q7 The malicious executable attempts to connect to an Internet host using an IP address which is hard-coded into it (there was no DNS lookup). What is the IP address of that Internet host? A7. 213.155.29.144 =============================================================================== This was a great puzzle! I had fun honing my forensic skills and learned a lot in the process. :) Additional Text: /******************************************************************************* * * xcte.c - Extract Chunked Transfer-Encoding from TCP stream files * * Copyright (C) 2010 - Christian North * *******************************************************************************/ #include #include #include #define version "v0.2 BETA" /******************************************************************************/ void usage() { printf("XCTE %s - ",version); printf("Extract Chunked Transfer-Encoding from TCP stream files\n"); printf("Usage: xcte \n"); exit(0); } /******************************************************************************/ int chunked_encoding(FILE *stream) { const char *encoding="Transfer-Encoding: chunked"; size_t len=1024; char data[len]; long offset=0; int bytes=0; int c=0; while(!feof(stream)){ if((bytes=fread(data,1,len,stream)) == 0) break; for(c=0;c<(bytes-1);c++){ if(data[c] == 0x0D && data[c+1] == 0x0A){ data[c]='\0'; offset+=strlen(data)+2; break; } } if(strstr(data,encoding) != NULL) { rewind(stream); return 1; } fseek(stream,offset,SEEK_SET); } return 0; } /******************************************************************************/ FILE *disposition(char *data) { const char *disposition = "Content-Disposition"; const char *filename = "filename="; FILE *fp = NULL; if(strstr(data,disposition) != NULL) { filename=strtok(data,"="); printf("Extracting Content: "); printf("%s\n",data+strlen(filename)+1); fp=fopen(data+strlen(filename)+1,"a"); return fp; } return NULL; } /******************************************************************************/ int extract(FILE *stream, FILE *content) { size_t chunk=0; size_t len=8; char *fragment; char data[len]; char hex[len]; while(!feof(stream)){ if(fread(data,1,len,stream) == 0) break; snprintf(hex,len,"%c%c%c%c",data[2],data[3],data[4],data[5]); chunk=strtoul(hex,NULL,16); if((fragment = malloc(chunk)) == NULL) break; if(fread(fragment,1,chunk,stream) == 0) break; fwrite(fragment,1,chunk,content); free(fragment); } fclose(content); return 0; } /******************************************************************************/ int main(int argc, char **argv) { char *streamfile=NULL; FILE *stream=NULL; FILE *content=NULL; size_t len=1024; char data[len]; long offset=0; int bytes=0; int c=0; if(argc != 2) usage(); streamfile = argv[1]; if((stream = fopen(streamfile,"r")) == NULL) usage(); if(!chunked_encoding(stream)){ printf("Transfer-Encoding: chunked - not found in "); printf("\"%s\"\n", streamfile); exit(0); } while(!feof(stream)){ if((bytes=fread(data,1,len,stream)) == 0) break; for(c=0;c<(bytes-1);c++){ if(data[c] == 0x0D && data[c+1] == 0x0A) { data[c]='\0'; offset++; break; } offset++; } content = disposition(data); if(content != NULL) break; fseek(stream,offset,SEEK_SET); } offset--; fseek(stream,offset,SEEK_SET); while(!feof(stream)){ if((bytes=fread(data,1,len,stream)) == 0) break; for(c=0;c<(bytes-4);c++){ if(data[c] == 0x0D && data[c+1] == 0x0A && data[c+2] == 0x0D && data[c+3] == 0x0A ){ offset+=2; fseek(stream,offset,SEEK_SET); extract(stream,content); fclose(stream); break; } offset++; } } return 0; } /******************************************************************************/