Skip to content

Instantly share code, notes, and snippets.

@NWPlayer123
Last active September 30, 2019 07:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NWPlayer123/d564229724636a7b7131db7077ac0ec1 to your computer and use it in GitHub Desktop.
Save NWPlayer123/d564229724636a7b7131db7077ac0ec1 to your computer and use it in GitHub Desktop.
Riivolution (and Devolution?) payload decryption algo
#Python doesn't support do while, so I do "while True" -> inverse check (if var1 == 1: break)
from struct import unpack, pack
import sys
bits_left = 0 #0x816107EC
decrypt_byte = 0
bytes_read = 0
DAT_816107F8 = 0
write_addr = 0
read_addr = 0
DAT_81610804 = 0
payload_start = 0
DAT_8161080C = 0
DAT_81610810 = 0 #no xrefs?
DAT_81610814 = 0
DAT_81610818 = 0
DAT_8161081C = 0
payload_entry = 0
table1 = [0] * 0x4EA #short, 2 bytes long
table2 = [0] * 0x4EA #short
table3 = [0] * 0x275 #short
table4 = [0] * 0x275 #short
table5 = [0] * 6 #word, 4 bytes long
table6 = [0] * 6 #short
table7 = [0] * 6 #word
# entry, flush_cache
#-----------------------------------------------------
def read_byte(f): #u8 read_byte(void)
global read_addr
byte = ord(f.read(1)) #*(payload_start + read_addr)
read_addr += 1
return byte
#-----------------------------------------------------
def write_byte(byte, o): #void write_byte(u8 byte)
global write_addr
o.write(chr(byte)) #*(payload_entry + write_addr)
write_addr += 1
#-----------------------------------------------------
def get_bit(f): #u8 get_bit(void)
global bits_left, decrypt_byte, bytes_read
bits_left -= 1
if bits_left == -1: #read another byte
decrypt_byte = read_byte(f)
bits_left = 7
bytes_read += 1
bit = decrypt_byte >> 7
decrypt_byte <<= 1
return bit & 1
#-----------------------------------------------------
def FUN_80D131C4(r3, r4): #void FUN_80D131C4(short r3, short r4)
global table1, table2, table3, table4
while True:
var1 = table1[r3]
table2[var1] = table2[r3] + table2[r4]
if var1 == 1: break
r4 = table4[table1[var1]]
if (r4 == var1):
r4 = table3[table1[var1]]
r3 = var1
if var1 == 1: break #do while var1 != 1
if table2[1] != 2000: return
for i in range(1, 0x4EA):
table2[var1] >>= 1
var1 += 1
#-----------------------------------------------------
def FUN_80D1326C(value): #void FUN_80D1326C(short value)
global table1, table2, table3, table4
value += 0x275
r10 = table1[value]
table2[value] += 1
if r10 == 1: return
r4 = table4[r10]
if (r4 == value):
r4 = table3[r10]
FUN_80D131C4(value, r4)
while True:
r10_val = table1[r10]
r10_val2 = r10_val
r4 = table4[r10_val2]
if r4 == r10:
r4 = table3[r10_val2]
if table2[r4] < table2[value]:
r9 = table4
if table4[r10_val2] == r10:
r9 = table3
r9[r10_val2] = value
r10_val2 = table4[r10] #overwrites 1 if we don't have another var
if r10_val2 == value:
table4[r10] = r4
r10_val2 = table3[r10]
else:
table3[r10] = r4
table1[r4] = r10
table1[value] = r10_val
FUN_80D131C4(r4, r10_val2)
value = r4
value = table1[value]
r10 = table1[value]
if r10 == 1: break #do while r10 != 1
#-----------------------------------------------------
def FUN_80D133D0(value, f): #short FUN_80D133D0(short value)
ret = 0
uVar1 = 1
if 0 < value:
while True:
bit = get_bit(f)
if bit != 0:
ret |= uVar1
value -= 1
uVar1 <<= 1
if value == 0: break #do while value != 0
return ret
#-----------------------------------------------------
def get_short(f): #short get_short(void)
global table3, table4
r29 = 1
while r29 < 0x275:
if get_bit(f) == 0:
r29 = table4[r29]
else:
r29 = table3[r29]
FUN_80D1326C(r29 - 0x275)
return r29 - 0x275
#-----------------------------------------------------
def setup_tables(): #checks out
global bits_left, decrypt_byte, bytes_read, DAT_816107F8, \
write_addr, read_addr, DAT_81610804, DAT_8161080C, \
DAT_81610814, DAT_81610818, DAT_8161081C, table1, \
table2, table3, table4, table5, table6, table7
for i in range(6):
table6[i] = 4 + (2 * i)
DAT_8161081C = 3
write_addr = 0
DAT_81610814 = 0
DAT_81610818 = 0
bits_left = 0
decrypt_byte = 0
DAT_816107F8 = 0
bytes_read = 0
read_addr = 0
for i in range(2, 0x4EA):
table1[i] = i >> 1;
table2[i] = 1;
for i in range(1, 0x275):
table3[i] = (i * 2) + 1
table4[i] = i * 2
l = 0
for i in range(6):
table5[i] = l
l += 1 << table6[i]
table7[i] = l - 1
DAT_81610804 = l - 1
DAT_8161080C = l + 0x3F
#-----------------------------------------------------
def decrypt_payload(f, o):
global DAT_816107F8, DAT_8161080C, table5, table6
buffer = [0] * 0x5600 #but *why*
bytes_wrote = 0
setup_tables()
short = get_short(f)
while short != 0x100:
if short < 0x100:
write_byte(short, o)
buffer[bytes_wrote] = short
bytes_wrote += 1
DAT_816107F8 += 1
if bytes_wrote == DAT_8161080C:
bytes_wrote = 0 #looks like debug?
else:
iVar1 = (short + -0x101) / 0x3E
iVar6 = short + iVar1 * -0x3E + -0xFE
short = FUN_80D133D0(table6[iVar1], f)
uVar8 = bytes_wrote - (short + iVar6 + table5[iVar1])
if uVar8 < 0:
uVar8 += DAT_8161080C #looks like debug?
uVar7 = bytes_wrote
short = iVar6
if 0 < iVar6:
while True:
write_byte(buffer[uVar8], o)
short -= 1
buffer[uVar7] = buffer[uVar8]
uVar7 += 1
uVar8 += 1
uVar5 = uVar8 ^ DAT_8161080C
uVar3 = uVar5 >> 31
uVar2 = uVar7 ^ DAT_8161080C
uVar4 = uVar2 >> 31
DAT_816107F8 += 1
uVar8 &= ((uVar3 - (uVar3 ^ uVar5)) >> 31)
uVar7 &= ((uVar4 - (uVar4 ^ uVar2)) >> 31)
if short == 0: break #do while short != 0
bytes_wrote += iVar6
if DAT_8161080C <= bytes_wrote:
bytes_wrote -= DAT_8161080C
short = get_short(f) #load new
#-----------------------------------------------------
#FUN_80D1376C global something
def entry2(f, o):
global payload_start, payload_entry
payload_start = 0x80D13820
payload_entry = 0x80A00000
decrypt_payload(f, o)
#flush_cache(0x80000000, 0x1800000); //flush entire MEM1
#(*(void*)0x80A00000)(); //they blrl to fuck with people(?)
#-----------------------------------------------------
with open("boot.elf", "rb") as f:
with open("output.bin", "wb") as o:
f.seek(0xD00) #too lazy to extract
entry2(f, o)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment