I have C snippet(decompiled from IDA) to be translated to Python:
# v29 = 0;
# v30 = -1342924972;
# while ( v29 < v62 ) // v62 is length of string to be decoded
# {
# v31 = (int *)v60;
# v32 = __ROL4__(v30, 3);
# v33 = *((_BYTE *)v31 + v29) - v29 - v32;
# v34 = (int *)v60;
# *((_BYTE *)v34 + v29) = v33;
# v35 = __ROR4__(v33, 11);
# v36 = __ROL4__(v30, 5);
# v30 = v30 + (v29++ ^ v36 ^ v35) - 1204489519;
# }
def decode_msg(dstr, str_len):
bstr = list(dstr)
v29 = 0
v32 = 0
v33=0
v35=0
v30 = -1342924972
while(v29 < str_len):
v32 = ((v30 & 0xffffffff) << 3) & 0xffffffff
v33 = ((hex(ord(bstr[v29])) & 0xff) - v32) & 0xff
bstr[v29] = v33 & 0xff
v35 = ((v33 & 0xffffffff) >> 11) & 0xffffffff
v36 = ((v30 & 0xffffffff) << 5) & 0xffffffff
v29 = v29 + 1
v30 = (v30 & 0xffffffff) + (v29 ^ v36 ^ v35) - 1204489519
return ''.join(bstr)
C code is in comments. The C code decodes a byte array, v60 is the array. I have error:
v33 = ((hex(ord(bstr[v29])) & 0xff) - v32) & 0xff
TypeError: unsupported operand type(s) for &: 'str' and 'int'
I am totally Python noob. I think hex() converts each item in dstr to a number. So why is it still str?
As mentioned, hex returns a string, which obviously does not support bitwise operations like & with a numeric type:
>>> type(hex(3))
<class 'str'>
>>> hex(3) & 0xf
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'str' and 'int'
The ord function already returns an int, so you can just remove the hex function altogether:
>>> ord('c') & 0xff
99
ord is already an int, you don't need the hex, which returns a string.
And I may be wrong, but this line may give you problems
bstr[v29] = v33 & 0xff
You'd need to cast it to string again:
bstr[v29] = chr(v33 & 0xff)
Related
This is the python code to get byte array and calculate SHA1 after performing concatenation of previous(n-1) hash with ibytes.
***for i in range(50000):
ibytes = pack("<I", i)
h = sha1(ibytes + h).digest()***
What could be the best possible way in C++ to implement above code,where I have C++ sha1 code already in place and accepts parameter of void* type.
I tried below code. But SHA value being generated is wrong starting from iterator == 0
BYTE pBuffer[24];
char fbuf[4];
sprintf(fbuf, "%02X%02X%02X%02X", (unsigned)val & 0xFF,
(unsigned)(val >> 8) & 0xFF,
(unsigned)(val >> 16) & 0xFF,
(unsigned)(val >> 24) & 0xFF);
pBuffer[0] = fbuf[0];
pBuffer[1] = fbuf[1];
pBuffer[2] = fbuf[2];
pBuffer[3] = fbuf[3];
memcpy(pBuffer + 4, hn, SHA_DIGEST_LENGTH);
Following the suggestions from #wohlstad and #john, I modified the code as
fbuf[0] = (unsigned)(val>>0) & 0xFF;
fbuf[1] = (unsigned)(val >> 8) & 0xFF;
fbuf[2] = (unsigned)(val >> 16) & 0xFF;
fbuf[3] = (unsigned)(val >> 24) & 0xFF;
This worked.
how to make 16bit to 8bit like that 0x0300 to 0x03 and 0x00 by python?
i try to it like that
reg = 0x0300
print(reg[0:4], reg[4::])..
it show me that 'int' object is not subscriptable
reg = 0x0316
regbinary = bin(reg)
print(regbinary)
regBotoom = regbinary[-8::]
print(regBotoom)
result = hex('0b'+regBotoom)
print(result)
it show me that
0b1100010110
00010110
TypeError: 'str' object cannot be interpreted as an integer
You can get lower and higher 8 bits with bitwise AND and shifting:
reg = 0x0316
lowBits = reg & 0xFF
highBits = (reg >> 8) & 0xFF
print(lowBits)
print(highBits)
Bitwise Operators:
x = 0x4321
y = x >> 8
= 0x43
z = x & 0x00ff
= 0x21
You can not manipulate an int like you are trying to do without converting it to a string first.
Perhaps you're after the answer #jafarlihi gave, where reg is really just an int and you shift its value to get the values you're after.
However, you may also want to see this:
import struct
reg = 790
regb = struct.pack('h', reg)
print(regb)
msb, lsb = struct.unpack('bb', regb)
print(msb, lsb)
regb_2 = struct.pack('bb', msb, lsb)
print(regb, regb_2)
value = struct.unpack('h', regb)
print(reg, value)
Result:
b'\x16\x03'
22 3
b'\x16\x03' b'\x16\x03'
790 (790,)
reg = 0x0300
print(hex((reg >> 8) & 0xFF))
print(hex(reg & 0xFF))
Output :
0x3
0x0
I have been trying to get my head around CRC32 calculations without much success, the values that I seem to get do not match what I should get.
I am aware that Python has libraries that are capable of generating these checksums (namely zlib and binascii) but I do not have the luxury of being able to use them as the CRC functionality do not exist on the micropython.
So far I have the following code:
import binascii
import zlib
from array import array
poly = 0xEDB88320
table = array('L')
for byte in range(256):
crc = 0
for bit in range(8):
if (byte ^ crc) & 1:
crc = (crc >> 1) ^ poly
else:
crc >>= 1
byte >>= 1
table.append(crc)
def crc32(string):
value = 0xffffffffL
for ch in string:
value = table[(ord(ch) ^ value) & 0x000000ffL] ^ (value >> 8)
return value
teststring = "test"
print "binascii calc: 0x%08x" % (binascii.crc32(teststring) & 0xffffffff)
print "zlib calc: 0x%08x" % (zlib.crc32(teststring) & 0xffffffff)
print "my calc: 0x%08x" % (crc32(teststring))
Then I get the following output:
binascii calc: 0xd87f7e0c
zlib calc: 0xd87f7e0c
my calc: 0x2780810c
The binascii and zlib calculations agree where as my one doesn't. I believe the calculated table of bytes is correct as I have compared it to examples available on the net. So the issue must be the routine where each byte is calculated, could anyone point me in the correct direction?
Thanks in advance!
I haven't looked closely at your code, so I can't pinpoint the exact source of the error, but you can easily tweak it to get the desired output:
import binascii
from array import array
poly = 0xEDB88320
table = array('L')
for byte in range(256):
crc = 0
for bit in range(8):
if (byte ^ crc) & 1:
crc = (crc >> 1) ^ poly
else:
crc >>= 1
byte >>= 1
table.append(crc)
def crc32(string):
value = 0xffffffffL
for ch in string:
value = table[(ord(ch) ^ value) & 0xff] ^ (value >> 8)
return -1 - value
# test
data = (
'',
'test',
'hello world',
'1234',
'A long string to test CRC32 functions',
)
for s in data:
print repr(s)
a = binascii.crc32(s)
print '%08x' % (a & 0xffffffffL)
b = crc32(s)
print '%08x' % (b & 0xffffffffL)
print
output
''
00000000
00000000
'test'
d87f7e0c
d87f7e0c
'hello world'
0d4a1185
0d4a1185
'1234'
9be3e0a3
9be3e0a3
'A long string to test CRC32 functions'
d2d10e28
d2d10e28
Here are a couple more tests that verify that the tweaked crc32 gives the same result as binascii.crc32.
from random import seed, randrange
print 'Single byte tests...',
for i in range(256):
s = chr(i)
a = binascii.crc32(s) & 0xffffffffL
b = crc32(s) & 0xffffffffL
assert a == b, (repr(s), a, b)
print('ok')
seed(42)
print 'Multi-byte tests...'
for width in range(2, 20):
print 'Width', width
r = range(width)
for n in range(1000):
s = ''.join([chr(randrange(256)) for i in r])
a = binascii.crc32(s) & 0xffffffffL
b = crc32(s) & 0xffffffffL
assert a == b, (repr(s), a, b)
print('ok')
output
Single byte tests... ok
Multi-byte tests...
Width 2
Width 3
Width 4
Width 5
Width 6
Width 7
Width 8
Width 9
Width 10
Width 11
Width 12
Width 13
Width 14
Width 15
Width 16
Width 17
Width 18
Width 19
ok
As discussed in the comments, the source of the error in the original code is that this CRC-32 algorithm inverts the initial crc buffer, and then inverts the final buffer contents. So value is initialised to 0xffffffff instead of zero, and we need to return value ^ 0xffffffff, which can also be written as ~value & 0xffffffff, i.e. invert value and then select the low-order 32 bits of the result.
If using binary data where the crc is chained over multiple buffers I used the following (using the OPs table):
def crc32(data, crc=0xffffffff):
for b in data:
crc = table[(b ^ crc) & 0xff] ^ (crc >> 8)
return crc
One can XOR the final result with -1 to agree with the online calculators.
crc = crc32(b'test')
print('0x{:08x}'.format(crc))
crc = crc32(b'te')
crc = crc32(b'st', crc)
print('0x{:08x}'.format(crc))
print('xor: 0x{:08x}'.format(crc ^ 0xffffffff))
output
0x278081f3
0x278081f3
xor: 0xd87f7e0c
I'm reverse engineering a proprietary network protocol that generates a (static) one-time pad on launch and then uses that to encode/decode each packet it sends/receives. It uses the one-time pad in a series of complex XORs, shifts, and multiplications.
I have produced the following C code after walking through the decoding function in the program with IDA. This function encodes/decodes the data perfectly:
void encodeData(char *buf)
{
int i;
size_t bufLen = *(unsigned short *)buf;
unsigned long entropy = *((unsigned long *)buf + 2);
int xorKey = 9 * (entropy ^ ((entropy ^ 0x3D0000) >> 16));
unsigned short baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
//Skip first 24 bytes, as that is the header
for (i = 24; i <= (signed int)bufLen; i++)
buf[i] ^= byteTable[((unsigned short)i + baseByteTableIndex) & 2047];
}
Now I want to try my hand at making a Peach fuzzer for this protocol. Since I'll need a custom Python fixup to do the encoding/decoding prior to doing the fuzzing, I need to port this C code to Python.
I've made the following Python function but haven't had any luck with it decoding the packets it receives.
def encodeData(buf):
newBuf = bytearray(buf)
bufLen = unpack('H', buf[:2])
entropy = unpack('I', buf[2:6])
xorKey = 9 * (entropy[0] ^ ((entropy[0] ^ 0x3D0000) >> 16))
baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
#Skip first 24 bytes, since that is header data
for i in range(24,bufLen[0]):
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
return str(newBuf)
I've tried with and without using array() or pack()/unpack() on various variables to force them to be the right size for the bitwise operations, but I must be missing something, because I can't get the Python code to work as the C code does. Does anyone know what I'm missing?
In case it would help you to try this locally, here is the one-time pad generating function:
def buildXorPad():
global xorPad
xorKey = array('H', [0xACE1])
for i in range(0, 2048):
xorKey[0] = -(xorKey[0] & 1) & 0xB400 ^ (xorKey[0] >> 1)
xorPad = xorPad + pack('B',xorKey[0] & 0xFF)
And here is the hex-encoded original (encoded) and decoded packet.
Original: 20000108fcf3d71d98590000010000000000000000000000a992e0ee2525a5e5
Decoded: 20000108fcf3d71d98590000010000000000000000000000ae91e1ee25252525
Solution
It turns out that my problem didn't have much to do with the difference between C and Python types, but rather some simple programming mistakes.
def encodeData(buf):
newBuf = bytearray(buf)
bufLen = unpack('H', buf[:2])
entropy = unpack('I', buf[8:12])
xorKey = 9 * (entropy[0] ^ ((entropy[0] ^ 0x3D0000) >> 16))
baseByteTableIndex = (60205 * (xorKey ^ (xorKey >> 4)) ^ (668265261 * (xorKey ^ (xorKey >> 4)) >> 15)) & 0x7FFF;
#Skip first 24 bytes, since that is header data
for i in range(24,bufLen[0]):
padIndex = (i + baseByteTableIndex) & 2047
newBuf[i] ^= unpack('B',xorPad[padIndex])[0]
return str(newBuf)
Thanks everyone for your help!
This line of C:
unsigned long entropy = *((unsigned long *)buf + 2);
should translate to
entropy = unpack('I', buf[8:12])
because buf is cast to an unsigned long first before adding 2 to the address, which adds the size of 2 unsigned longs to it, not 2 bytes (assuming an unsigned long is 4 bytes in size).
Also:
newBuf[i] = xorPad[(i + baseByteTableIndex) & 2047]
should be
newBuf[i] ^= xorPad[(i + baseByteTableIndex) & 2047]
to match the C, otherwise the output isn't actually based on the contents of the buffer.
Python integers don't overflow - they are automatically promoted to arbitrary precision when they exceed sys.maxint (or -sys.maxint-1).
>>> sys.maxint
9223372036854775807
>>> sys.maxint + 1
9223372036854775808L
Using array and/or unpack does not seem to make a difference (as you discovered)
>>> array('H', [1])[0] + sys.maxint
9223372036854775808L
>>> unpack('H', '\x01\x00')[0] + sys.maxint
9223372036854775808L
To truncate your numbers, you'll have to simulate overflow by manually ANDing with an appropriate bitmask whenever you're increasing the size of the variable.
>>> a = -2147458560
>>> bin(a)
'-0b1111111111111111001111000000000'
My intention is to manipulate a as 32-bit signed binary and return it. The correct conversion for -2147458560 would be '0b10000000000000000110001000000000'; how can I achieve that?
Bitwise AND (&) with 0xffffffff (232 - 1) first:
>>> a = -2147458560
>>> bin(a & 0xffffffff)
'0b10000000000000000110001000000000'
>>> format(a & 0xffffffff, '32b')
'10000000000000000110001000000000'
>>> '{:32b}'.format(a & 0xffffffff)
'10000000000000000110001000000000'