0

i have snippet code that i want to convert to python to understand the types that ghidra use such *(byte *) and *(code *) and *(uchar *) etc..

the first code:

void one(int param_1,int param_2) {
  int local_8;
  
  local_8 = 0;
  while (local_8 < param_2) {
    *(byte *)(param_1 + local_8) = *(byte *)(param_1 + local_8) ^ 0x50;
    local_8 = local_8 + 1;
  }
  return;
}

local_14 = 0;
byte local_12c [256];
local_24 = strlen(param_4);
local_10 = 0;

while (local_14 < 0x100) {
   local_12c[local_14] = (byte)local_14;
   local_14 = local_14 + 1;
}
local_18 = 0;
while (local_18 < 0x100) {
  iVar1 = (int)param_4[local_18 % (int)local_24] + (uint)local_12c[local_18] + local_10;
  uVar2 = (uint)(iVar1 >> 0x1f) >> 0x18;
  local_10 = (iVar1 + uVar2 & 0xff) - uVar2;
  swap(local_12c + local_18,local_12c + local_10);
  local_18 = local_18 + 1;
}

writing a python code for this code it will help me a lot to understand the logic that ghidra use with these kind of instructions such as swap(local_12c + local_18,local_12c + local_10); is it a number value ? how to swap a numbers without variables

7
  • but why do you want to convert the code in python? python doesn't use explicit types – R4444 May 4 at 5:03
  • 2
    It looks like RC4. I think it could be cleaned up in Ghidra to get more understanding of the code – Paweł Łukasik May 4 at 5:05
  • because i want to understand the logic here @R4444 – K. John Michel May 4 at 7:25
  • how did you know that ? @PawełŁukasik and how ghidra can cleaned up to get more understanding of the code ? – K. John Michel May 4 at 7:27
  • Hi and welcome to RE.SE. So what's the question? – 0xC0000022L May 4 at 7:42
2

As Paweł Łukasik point out, it looks like RC4 indeed.

That's especially true for the KSA that you can immediately recognize:

local_14 = 0;

while (local_14 < 0x100) {
     local_12c[local_14] = (byte)local_14;
     local_14 = local_14 + 1;
}

If you rename the variables by keeping in mind that this is a Key-Scheduling Algorithm, you end up with the standard RC4 KSA:

SBOX[256];
i = 0;
while (i < 256) {
     SBOX[i] = i
     i += 1;
}

After that, the next block must be a Pseudo-random generation algorithm (PRGA):

local_18 = 0;
while (local_18 < 0x100) {
     iVar1 = (int)param_4[local_18 % (int)local_24] + (uint)local_12c[local_18] + local_10;
     uVar2 = (uint)(iVar1 >> 0x1f) >> 0x18;
     local_10 = (iVar1 + uVar2 & 0xff) - uVar2;
     swap(local_12c + local_18,local_12c + local_10);
     local_18 = local_18 + 1;
 }

Once again, try to rename everything as if it was a RC4 PRGA:

i = 0;
j = 0;
while (i < 256) {
     iVar1 = param_4[i % len_para_4] + SBOX[i] + j;
     uVar2 = (iVar1 >> 0x1f) >> 0x18;
     j = (iVar1 + uVar2 & 0xff) - uVar2;
     swap(SBOX + i ,SBOX + j);      
     i += 1
}

The 'swap' function exchange the value of SBOX[i] with the value of SBOX[j], wich is again, a standard thing in the RC4 algorithm.

I think you now have everything to re-write this in Python if you want to. But regarding your question, this is not going to help you with the variable's types, as Python does not works that way. Keep in mind that you will probably spend more time fighting with Python's types than implementing the algorithm.

If you really want to re-write this, your best option is to do so in C, you'll be able to play with your pointers *(byte *) and *(code *), ...

In my opinion, you'll gain some time by simply debugging the program and inspect the values that you are curious about.

EDIT: Your last question can be answered using the same method.

You have this block of code:

local_8 = 0;
while (local_8 < param_2) {
     *(byte *)(param_1 + local_8) = *(byte *)(param_1 + local_8) ^ 0x50;
     local_8 = local_8 + 1;
}

After cleaning up a bit, it look like:

i = 0;
while (i < param_2) {
     param_1[i] = param_1[i] ^ 0x50;
     i += 1
}

Basically you are passing two arguments to your function (param_1 and param_2). The fist one is an array, the second one is the length of that array. This small routine will take every bytes of your array, and xor it with 0x50, before putting it back into the original array.

2
  • Thank you @Guillaume , and this one *(byte *)(param_1 + local_8) = *(byte *)(param_1 + local_8) ^ 0x50; if i want to translate to python or any scripting langauge, how it will be ? – K. John Michel May 4 at 10:17
  • Same approach, you just have to rename the variable, and you'll easily find what it does. I'll edit my initial answer, it's a pain to format code here :) – Guillaume May 4 at 11:00
0

There are several implementations of python rc4 available in GitHub repositories

As Already pointed out You need to Cleanup and Rename all those local_xxx names

in the answer above by @Guillaume it seems he is implying the Array Initialization part as KSA and the KSA as PRGA
I don't think you have posted the PRGA in your query

the Array Initialization part can be done with a onliner as below

S=list(range(256))  

the KSA in the query above contains few junk lines
which can be safely removed for example right shifting a 32bit by 0x1f and then by 0x18 will always result in 0

so substituting 0 in place of uVar2 you can see local_10 will always be iVar1 so you can simply eliminate the local_10

and a swap in python can be a tuple exchange
the first function in your query is a xor exchange function
so based on the above premise you can simply recode in python as below
the code below generates two keystreams for two plaintexts

def one(a,b):
    i=0
    while(i<b):
        a[i] = a[i] ^ 0x50
        i=i+1
    return a
print(one([1,2,3,4,5],5),"\n***************************\n")


S = list(range(256))
print(S[0:16])
Key = [b"Attack at dawn",b"Defend at Night"]
k=0
j=0
inLen=len(Key)
for k in range(0x256):
    k=( ( k + S[j] + Key[0][j%inLen] ) % 256 )
    S[j],S[k]=S[k],S[j] 
print(S[0:16])
for k in range(0x256):
    k=( ( k + S[j] + Key[1][j%inLen] ) % 256 )
    S[j],S[k]=S[k],S[j] 
print(S[0:16]) 

executing this you should get something like this

:\>python conv2py.py
[81, 82, 83, 84, 85]
***************************

S_initial    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] 
S_for_Key[0] [104, 16, 114, 140, 4, 95, 6, 0, 89, 203, 219, 212, 25, 117, 14, 215]
S_for_Key[1] [199, 217, 227, 209, 193, 123, 190, 75, 189, 161, 153, 168, 111, 92, 152, 203] 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.