Vault7: CIA Hacking Tools Revealed
Navigation: » Latest version
Owner: User #20251227
Python Snippets - Cross Platform? Only a bit.
Introduction
Doing cross-platform development using Python on both Windows & Linux? Are your Windows & Linux boxen 64-bit? Are you doing binary manipulations (e.g., struct.pack() / struct.unpack() )? You might be in for some fun, and I don't mean the conventional definition of "fun" either.
Python, being the cross-platform language/runtime/interpreter that it is, tends to be rather handy. Unfortunately, at some point the rubber needs to meet the road, and Python's consistent, platform-independent behavior becomes platform DE-pendent. This can cause hilarity to ensue when doing things such as inheriting socket options on a new socket as the across an 'accept' call, and dealing with things at the binary level (e.g., via ctypes).
To see the issue, lets run the following snippet of code:
Let's see the output if we run the above on a Windows 32-bit box:
note the sizes of the 'long' and 'unsigned long'.
Now, let's look at the output for a 64-bit Windows box:
The result seems intuitively pleasing, everything appears to have the same size except for the last item which is a pointer.
Now, for the twist. What, praytell, happens to the output if we run on a 64-bit Linux box?
pad byte looks OK, short matches, long is 8, wait...what?!? Note the values for long and unsigned long...they don't match with the 64-Bit Windows box (or the 32-bit Windows box for that matter). WTF?
Well, it turns out that this is due to the underlying 64 bit memory/programming model in use by Linux (BSDs should operate similarly). When going to a 64-bit programming model, it turns out that there are a few different ways to handle the widths of certain types. The Windows folks chose to use the model known as "LLP64" (1)(3), which means that the "Long Long" and "Pointer" types get treated as 64-bit wide quantities. The *nix world decided to go with the "LP64" model(4), which means that the "Long", "Long Long", and "Pointer" types get treated as 64-bit wide quantities.
As can be imagined, this can create a bit (hah!) of an issue when trying to write cross-platform 64-bit code. This can be even more of an issue if one is accustomed to Python's nominal "cross platform independence".
Thus, when writing Python code which is expected to run on 64-bit boxes, one should pay very close attention to types (e.g., Long) which can have their bitness changed if the underlying platform changes. Note that the example above shows what can happen when using the 'struct' module. The same holds true for the behavior of the ctypes module.
Have Fun (in the conventional sense)!
References
(1)Abstract Data Models, msdn.microsoft.com/en-us/library/windows/desktop/aa384083(v=vs.85).aspx ,Last Accessed 26-Aug-2015
(2)"Chapter 1: Introduction to Win32/Win64", UNIXOperating system Custom Application Migration Guide, technet.microsoft.com/en-us/library/bb496995.aspx ,Last Accessed 26-Aug-2015
(3)Chen, R., "Why did the Win64 team choose the LLP64 model?", "The Old New Thing Blog", 31-Jan-2005, blogs.msdn.com/b/oldnewthing/archive/2005/01/31/363790.aspx ,Last Accessed 26-Aug-2015
(4)64-Bit Programming Models: Why LP64?, www.unix.org/version2/whatsnew/lp64_wp.html
(5)"What is the bit size of long on 64-bit Windows", stackoverflow.com/questions/384502/what-is-the-bit-size-of-long-on-64-bit-windows