Creating a toy virtual machine with PyPy
Here, you can use “virtual machine” as in “Java Virtual Machine”, not as in virtualization. We will play with the virtual machine described in the paper Tracing the Meta-Level: PyPy’s Tracing JIT Compiler by C.F. Bolz, A. Cuni, M. Fijalkowski and A. Rigo (it’s a great read by the way).
PyPy is a fascinating project, too complex to describe here. Among other things, PyPy can take any interpreter written in a subset of Python, translate it to C, and automatically generate a JIT compiler for this language. Does it sound too good to be true? Let’s try this.
- grab PyPy source code
- create the interpreter in pypy/translator/goal/target-toy.py with the following code:
import os, sys
import autopath
import py
# these are the opcodes for the interpreted language
JUMP_IF_A = 1
MOV_A_R = 2
MOV_R_A = 3
ADD_R_TO_A = 4
DECR_A = 5
RETURN_A = 6
from pypy.rlib.jit import JitDriver
tlrjitdriver = JitDriver(greens = ['pc', 'bytecode'],
reds = ['a', 'regs'])
# the main interpreter loop
def interpret(bytecode, a):
regs = [0] * 256
pc = 0
while True:
tlrjitdriver.jit_merge_point(bytecode=bytecode, pc=pc, a=a, regs=regs)
opcode = bytecode[pc]
pc += 1
if opcode == JUMP_IF_A:
target = bytecode[pc]
pc += 1
if a:
if target<pc:
tlrjitdriver.can_enter_jit(bytecode=bytecode, pc=target, a=a, regs=regs)
pc = target
elif opcode == MOV_A_R:
n = bytecode[pc]
pc += 1
regs[n] = a
elif opcode == MOV_R_A:
n = bytecode[pc]
pc += 1
a = regs[n]
elif opcode == ADD_R_TO_A:
n = bytecode[pc]
pc += 1
a += regs[n]
elif opcode == DECR_A:
a -= 1
elif opcode == RETURN_A:
return a
# __________ Entry point __________
def entry_point(argv):
# the program we want to interpret
# it computes the square of its argument
bytecode = [
MOV_A_R, 0, # i = a
MOV_A_R, 1, # copy of ’a’
# 4:
MOV_R_A, 0, # i--
DECR_A,
MOV_A_R, 0,
MOV_R_A, 2, # res += a
ADD_R_TO_A, 1,
MOV_A_R, 2,
MOV_R_A, 0, # if i!=0: goto 4
JUMP_IF_A, 4,
MOV_R_A, 2,
RETURN_A
]
result = interpret(bytecode, int(argv[1]))
print result
return 0
def jitpolicy(driver):
from pypy.jit.metainterp.policy import JitPolicy
return JitPolicy()
# _____ Define and setup target ___
def target(*args):
return entry_point, None
# main function, if this script is called from the command line
if __name__ == '__main__':
entry_point(sys.argv)
- the lines in italic are the annotations for the JIT compiler. We need to give PyPy some insight on the interpreted language by declaring what is the instruction pointer (the green variables), the beginning of the dispatch loop and the backward branches (see the paper for full details).
- check that you can execute this script correctly by running
python target-toy.py 12, the output should be 144 - PyPy can translate this script in C. For this, first install the dependencies and then run the following command:
python translate.py target-toy.py - this should give you an executable target-toy-c, rename it target-toy-native and check that
./target-toy-native 12yields 144 - now we can ask PyPy to translate target-toy.py in C and generate a JIT compiler for it. For this, we just run
python translate.py --opt=jit target-toy.py- note: the 64-bit backend of PyPy is not implemented yet, so if you are on a 64-bit system, you will have to struggle a bit. You will have to use a 32-bit Python interpreter (see my former post), create an alias for gcc -m32 (let’s call it gcc32) and then pass the option –cc=gcc32 to translate.py.
- this should give you another target-toy-c executable, rename it to target-toy-jit and check that
./target-toy-jit 12 yields 144
Ok, everything is working, so let’s now see how all this performs by computing large squares:
~/pypy-trunk/pypy/translator/goal$ time python target-toy.py 1000000
1000000000000
real 0m18.637s
~/pypy-trunk/pypy/translator/goal$ time ./target-toy-native 1000000
-727379968
real 0m0.024s
~/pypy-trunk/pypy/translator/goal$ time ./target-toy-jit 1000000
-727379968
[...]
real 0m0.005s
The first run is the square program interpreted by our program, itself interpreted by the Python interpreter. Double interpretation is slow.
The second run is the square program interpreted by a native version of our interpret function. Interpretation by native code is ok.
The third run is the square program interpreted and JIT’ed on the fly. It’s super awesome :)
Final note: I must thank everybody from #pypy on freenode, for their help and resilience to stupid questions. Thanks guys!
How to build 32-bit Python on Ubuntu 9.10 x86_64
This might be useful to someone:
$ cd Python-2.6.4
$ CC="gcc -m32" LDFLAGS="-L/lib32 -L/usr/lib32 \
-L`pwd`/lib32 -Wl,-rpath,/lib32 -Wl,-rpath,/usr/lib32" \
./configure --prefix=/opt/pym32
$ make
$ sudo make install
Now, to check if the build is correct, try to check the max integer size on your standard 64-bit interpreter and in your fresh 32-bit binary:
$ python -c "import sys; print sys.maxint"
9223372036854775807
$ /opt/pym32/bin/python -c "import sys; print sys.maxint"
2147483647
No Offline Google Maps on Android
If you ever wondered why you don’t have mapping applications on Android that let you cache Google maps data (for when you have no Internet connectivity), that’s because it’s forbidden in the Android Maps API terms of service:
- abroad (unless you can afford astronomical roaming charges of course),
- hiking in the backcountry
UPDATE: the OruxMaps application on Android can read offline maps created with the TrekBuddy desktop application. This app can create maps from a number of different sources, including Google maps topographic data. Let’s celebrate!
Getting Started with Savarin
(disclaimer: the author of Savarin, Matthieu Kaczmarek, is a colleague working in the office next door and a friend of mine)
Savarin is a free online binary classification service (you can think of it as automatic diff’ing against large databases of programs). It is in beta, not fully polished yet, but you can still squeeze some interesting results out of it. Here is your daily shot of binary analysis, freshly brewed.
You will need:
- 2 different malware samples in the same malware family. We are going to use Sasser.A (already in Savarin’s database) and an unpacked Sasser.G (md5 b973853d0863070aca89ce00d4ee0fb9 [offensivecomputing.net])
- IDA with IDAPython for the actual diff’ing (I have IDA 5.5, I don’t know if this works with the free version)
Let’s go:
- open Savarin
- in “Classification against custom database”, choose SasserA
- upload the Sasser.G sample
- in the results page, click More to see the similarity with other binaries in the Sasser family
- you can see that the sample is 41.95% similar to a sample with md5 edc66a4031f5a41f9ddf08595a1d4c92
At this point, you have a classification of a sample against a (small) database of programs. You can therefore see the distance between this sample and other samples. If you ask me, it’s a lot better to see that unknownsample.exe is 80% similar to badguy.exe and 90% similar to badguy2.0.exe than just “infected” or “not infected”.
For the actual diff’ing, follow these steps:
- open the Sasser.G sample in IDA
- download the IDAPython analysis report on Savarin’s analysis page (this report contains all the data needed to visualize the binary differences in IDA)
- execute the IDAPython analysis report
- right now, the situation is pretty anticlimactic since you should see no change apart from a few lines in the console. Wait until next step for the interesting stuff. Yes, you had nothing to do in this step, so what?
- type SavColor(‘md5.edc66a4031f5a41f9ddf08595a1d4c92′, 0×0088ff) in the IDAPython console (it is the md5 value of the Sasser.A sample)
- type SavComment(‘md5.edc66a4031f5a41f9ddf08595a1d4c92′) in the IDAPython console
- this is it, now you can browse the Sasser.G sample, and the common parts with Sasser.A will be colored. Additionally, for two matching instructions you will see the corresponding address in the Sasser.A sample.
The Fine Screenshots:
1998 has called and they want their software back
“The need to improve current industrial software engineering practice is widely felt. To mention only a few striking examples: too many software projects fail and are canceled before completion or are not delivered on time or exceed their budget the energy spent on testing code is ever increasing and tends to represent more than half of the entire development cost, the number of errors found in complex software is ofter rather high, there is almost no software warranty whatsoever, but again and again the world is surprised by Trojan horses and security holes, etc.”
– Abstract State Machines, Egon Börger and Robert Stärk, 1998
Packers, egg, sausage and packers
Thanks to Silvio Cesare and Felix Gröbert, I now have 44 species in my packer zoo. I tested TraceSurfer on these 44 packers, here are the full results and the visualizations.
(quick recap: TraceSurfer uses Pin to trace every instruction in target binaries, extracting a trace file. Then the trace is analysed (or surfed) to detect layers of self-modifying code (or code waves) and code protection patterns)
Highlights:
- only 35 binaries execute correctly on my machine
- Pin v. 31933 works on 30 of these binaries (success rate of 85.71%)
- some packers don’t seem to pack anything since they have only 1 code wave (!Epack Lite 1.4, Pepack, VmProtect). Either the binaries are indeed packed and I fail to detect the self-modifying code, or they’re not self-modifying at all. It’s probably the latter, since the trace sizes are very close to the original (unpacked) binary.
- very few packers seem to use code scrambling (supposedly an advanced anti-dumping technique): Acprotect, Petite and the Yoda family
- integrity checking seems to be more popular, it is used in Acprotect, Themida, Enigma, Pelock, NSPack…
- given the trace size, it seems that anti-emulation loops can be found in Morphine (164M instructions) and !Epack 1.0 (87M instructions)
- nice similarities between Yoda Crypter 1.3 and Yoda Protector 1.4
- the Monster Award is attributed to… Themida 1.8.5.2 (80M instructions, 31 code waves, 142890 decrypted bytes + integrity checking)
Independent Trekking in Northern Vietnam
Right after Deepsec, I attended SEFM09 in Hanoi, Vietnam. I wanted to explore the backcountry with my girlfriend and I would like to provide some feedback to people planning something similar.
We wanted to avoid popular tourist destinations like Sapa and Halong Bay, so we decided to visit Ba Be lake. Planning the trip is not exactly simple, as information about the area is hard to find. For instance, the Lonely Planet says approximately “the lake is nice, there are some guest houses, getting there by bus sucks”. Well, we confirm all that.
- make sure to take enough cash with you, there are no ATMs or banks there
- avoiding overcharging is not something easy, since prices are never written explicitly. Always try to know the “normal” price for a taxi or bus ride beforehand, and prepare this amount of money in one of your pockets (keep the rest of your money in other pockets). This is important since sometimes you can’t really expect change.
- take some pens and paper. Most people outside touristic circuits don’t speak English, so it is quite helpful to draw sketches, write prices and the name of places (since the Vietnamese pronunciation is far from obvious)
- learn a few Vietnamese words and how to pronounce them. We found this list useful:
- hello: xin chao
- thank you: cam o’n
- goodbye: tam biet
- beer: bia
- from the Old Quarter to Luong Yen bus station, a taxi takes 10 min and 50.000 VND, but you can go there by foot in 30 min.
- at Luong Yen bus station, take a bus for Bac Kan/Cao Bang. It leaves theoretically at 6:15 am but be flexible. It’s a 3-4 hours drive, 70.000 VND.
- at Bac Kan, a bus leaves at 11:45 am for Cho Ra, 2-3 hours drive. We got ripped off at this point and had to pay 100.000 VND, the local price was 30.000 VND.
- at Cho Ra, you’ll easily find a moto-taxi that will take you to Ba Be. Or rather, they will find you. It takes an additional 30 min and you’re almost there (50.000 VND).
Warning: the motorbikes did not exactly bring us to Ba Be, they left us in front of a dull hotel in the middle of nowhere. The manager “welcomed” us with tea and pushed his products really hard (rooms with internet, trekking and boat tours…). We were put off by his aggressive marketing, so we took our backpacks and literally fled. It took 1h30 to walk to Pac Ngoi (so we ended up there at dusk, that is to say at 5:30 pm).
For the return trip, a minibus leaves Pac Ngoi’s bridge for Bac Kan at 7:00 am, 30.000 VND. From there, getting back to Hanoi is easy but you might not end up in Luong Yen. Our bus arrived at My Dinh bus station, quite far from the old quarter… (taxi for Hoan Kiem, 150.000 VND)
We were suddenly not too adventurous and decided to stay in the only guesthouse that the Lonely Planet recommends, Hoa Son in Pac Ngoi. It was indeed a nice place, clean, with hot water, OK beds, and awesome meals prepared by a really friendly family. The night costs 60.000 VND per person, dinner 60.000 VND and breakfast 30.000 VND. There are some 4-5 other guest houses in Pac Ngoi, and a bunch of others in the next village. The village (I think its name is Bo Lu) does not appear on Google Maps, but it is roughly located here.
Ok, now the interesting part. The two main activities in Ba Be are the boat tour around the lake, and trekking.
The boat tour is nice and relaxing after a full day in local buses. You can easily find a boat in Bo Lu that will take you around for 4-5 hours, 450.000 VND. There is the bat-filled Puong cave here, and the Dau Dang waterfalls here (don’t expect something amazing). You can have an excellent meal next to Dau Dang in a very simple but cool setting.
Trekking
Trekking in the area is not easy but possible. Some random tips:
- I took a gas and an alcohol stove, but we were unable to find any fuel in the appropriate format in Hanoi. They looked really puzzled by my gas stove. It is a standard hiking stove, but it is clearly not that standard in Vietnam. Trekking without being able to boil water or cook food is a problem.
- we could not find a good map of the region. That makes trekking without a guide difficult. Our solution was to print Google Maps topographic pages on A3 plastified paper and “guessing” potential trails. Warning: at the time of writing, some roads, trails, villages and rivers around Ba Be do not appear on Google Maps. We also had a hiking GPS, but with virtually no background maps.

- don’t go south of Pac Ngoi, except if you like dull roads and filthy villages. The Ban Duong waterfall is not worth it, and Cho Leng is an awful town.
So we faced a lot of problems, but still had an amazing trekking day. I won’t give the detailed itinerary to avoid spoiling the region, but there are some trails and a really nice areas west of the lake (according to this guy, the area north of the Nang river is also worth a look).
We headed to Bo Lu and tried to head north, crossing several small villages on the way. We followed a trail for a while, and after crossing a (small) river, a guy told us “H’mong” and invited us to follow him. So we did. He led us to a mountaineous area where the landscape was amazing, revealing a maze of trails, rice fields and H’mong houses. Our improvised guide was named Vao, and after 3h30 of hiking he invited us to drink the tea with his family. Before leaving him, he proudly showed us the new house he was building. The GPS turned out to be useful, as we had to walk in the jungle to reach Dau Dang before the night. We ended the trek by hiring a boat to take us back to Pac Ngoi under the moonlight.
All in all, an incredible trip.
The Sad State of Computer Security
Current computer systems have very serious, fundamental problems. And these problems can be technically exploited by attackers to run arbitrary code on our machines. So I guess we can all agree that the situation right now is somewhere between very bad and super bad. What is even more surprising is our reaction to this situation: we focus on preventing the technical exploitations of the flaws, and we leave the underlying problems intact. This leads to absurd “solutions” such as ASLR, which make it harder to develop reliable exploits and leave the initial problem (memory corruption) untouched. In a way, it’s like adding a bulletproof jacket to a dead body: sure the jacket might stop some bullets, but the body was dead in the first place. There are some really smart guys out there in the industry, and they discuss how to make really sophisticated bulletproof vests and what their weaknesses are, but nobody seems to notice that the body they’re trying to protect is dead anyway.
The fundamental problems that I mentioned earlier are that we don’t know how to produce programs without vulnerabilities, and we don’t know how to analyze compiled programs.
- we don’t know how to produce programs without vulnerabilities: or rather, we know how to avoid large classes of vulnerabilities such as memory corruption bugs with type-safe languages but we prefer sticking with unsafe languages such as C. “Hey that’s crazy, why is that?”, you wonder. The only reason I can see is performance: right now nobody rivals with the speed and memory usage of C/C++ programs. In my opinion, it’s just a matter of time before new languages beat the performance of C (yes, you can go faster-than-C). And hopefully, we’ll forget about memory corruption bugs altogether. Note that it will still be a long way from producing *correct* programs, but that will already be an important milestone.
- we don’t know how to analyze compiled programs, or rather we know that compiled programs are impossible to analyze. I already explained that bit in a post about malware analysis. The good side is that if we wanted, we could make programs statically analyzable (security-wise). I’m talking about binaries here, and this is no science fiction: just check out Google NaCl and the permission system on Android devices. We just have to decide that we want this kind of binaries to become standard desktop executables, and that would partly free us from the dependance to AV signatures updates.
Deepsec slides and tool releases

Deepest apologies to Edward Hopper
I’m writing this from deepsec, where I just finished my talk [slides] about dynamic instrumentation. It was a wrap up of what I did last year with Pin (malware analysis, unpacking) and a Javascript deobfuscator I didn’t blog about.
Some of you might be happy to know that the tools are now available at Google code:
- Crême Brûlée: Javascript deobfuscation using dynamic instrumentation
- Tarte Tatin Tools: my set of pintools for tracing and unpacking (including an IDA Python script)
As you might guess, the tools are more prototypes than anything else, and I advise you to use them only if you feel really adventurous.
The Sad State of Reverse Engineering
When you look at software engineering as a research field, you can see some pretty serious progress there. There are amazing projects like PyPy and LLVM, massive optimizations in gcc and JIT compilers (HotSpot, Psyco, TraceMonkey). Compared to that, I have the impression that the reverse engineering community did not produce any significant results. What we have is disassemblers, that is to say parsers.
To make things even worse, the more advanced tools used in RE have been created for a totally different purpose (think Pin, VEX, QEMU, Bochs, virtualization…). Some nice works are being performed by folks like Sean Heelan, Silvio Cesare, the Sogeti R&D team (metasm, fuzzgrind) and the BitBlaze team (TEMU, Vine). But overall I can see no open, community-driven, formally sound approach. The tools are either not FOSS, limited in scope, or just not-that-reusable.
There is a number of potential factors to explain the situation:
- reversers are not developers (this, I think, is a big factor)
- reversers are solitary, basement programmers (not to mention cheese pops and japanese tentacle porn)
- the complexity of x86 + Windows makes the entry cost too high for academics
We are therefore left with a research niche with virtually no academics, little to no developer community, that still pumps some big bucks. The only player left is the security industry, i.e. corporations which have absolutely no incentive to solve the problem.
Did I miss something, or is the picture really that grim?








