前言
❝
猿人学 2020 app 逆向 比赛,第一题
❞
❝
为啥写第一题,因为最简单,懒 ~
❞
java 层分析
祭出群友传的神器 jadx-gui
反编译分析一把梭 ...... 中间省略 n 个字,最终定位到 sign
参数的加密逻辑
简单分析下,看到 abcd
四个常量,第一反应是 md5
算法,然后祭出逆向之友,结果不一样,初步怀疑是魔改算法,继续分析代码
没有发现 T
表,此时就开始怀疑这是 md5
吗 ?,了解 md5
算法的小伙伴都知道,每一轮分别会执行四个函数 f g h i
每个函数调用 16
次
但是这个样本只有三个函数 f g h
每个函数也只循环调用了 4
次,很明显有猫腻,但是为了比赛的速度,决定放弃 python
还原,直接复制 java
第一题算是过了
python 还原
比赛结束后,题目的原创大佬 Q佬
为我们解答了,是 md4
算法,此时才明白,Q佬 不愧是 Q老
java
跑起来之后再使用 python
就简单了许多,对照着改 就完事了
0x1
复制 abcd
四个常量
0x2
class Md4Hash(object):
def __init__(self):
self.A = 0x67452301
self.B = 0xefcdab89
self.C = 0x98badcfe
self.D = 0x10325476
def padding(self):
self.msg_bit_len = len(self.msg) * 8
self.msg_len = self.msg_bit_len % (2 ** 64)
self.msg += b'x80'
pad_leg = ((448 - (self.msg_len + 8) % 512) % 512) // 8
self.msg = self.msg + b'x00' * pad_leg + self.msg_len.to_bytes(8, byteorder='little')
self.msg_bit_len = len(self.msg) * 8
def main(self, msg):
self.msg = msg.encode()
self.padding()
padding
函数
0x3
def transform(self):
iterations = self.msg_bit_len // 512
for i in range(0, iterations):
a = self.A
b = self.B
c = self.C
d = self.D
block = self.msg[i * 64:(i + 1) * 64]
M = self.__block_divide(block, 16)
i1_arr = [0, 4, 8, 12]
for i1 in range(4):
i11 = i1_arr[i1]
a = self.__FF(a, b, c, d, M[i11], 3)
ff = self.__FF(d, a, b, c, M[i11 + 1], 7)
c = self.__FF(c, ff, a, b, M[i11 + 2], 11)
b = self.__FF(b, c, ff, a, M[i11 + 3], 19)
d = ff
i2_arr = [0, 1, 2, 3]
for i2 in range(4):
i22 = i2_arr[i2]
a = self.__GG(a, b, c, d, M[i22], 3)
d = self.__GG(d, a, b, c, M[i22 + 4], 5)
c = self.__GG(c, d, a, b, M[i22 + 8], 9)
b = self.__GG(b, c, d, a, M[i22 + 12], 13)
i3_arr = [0, 2, 1, 3]
for i3 in range(4):
i33 = i3_arr[i3]
hh = self.__HH(a, b, c, d, M[i33], 3)
d = self.__HH(d, hh, b, c, M[i33 + 8], 9)
c = self.__HH(c, d, hh, b, M[i33 + 4], 11)
b = self.__HH(b, c, d, hh, M[i33 + 12], 15)
a = hh
self.A = (self.A + a) % (2 ** 32)
self.B = (self.B + b) % (2 ** 32)
self.C = (self.C + c) % (2 ** 32)
self.D = (self.D + d) % (2 ** 32)
return self.__fmt8(self.A) + self.__fmt8(self.B) + self.__fmt8(self.C) + self.__fmt8(self.D)
transform
函数
0x4
@staticmethod
def __F(i, i2, i3):
return ((~i) & i3) | (i2 & i)
@staticmethod
def __G(i, i2, i3):
return (i & i3) | (i & i2) | (i2 & i3)
@staticmethod
def __H(i, i2, i3):
return (i ^ i2) ^ i3
def __FF(self, a, b, c, d, m, s):
result = self.left_circular_left((a + self.__F(b, c, d) + m), s)
return result
def __GG(self, a, b, c, d, m, s):
result = self.left_circular_left((a + self.__G(b, c, d) + m + 1518565785), s)
return result
def __HH(self, a, b, c, d, m, s):
result = self.left_circular_left((a + self.__H(b, c, d) + m + 1859775393), s)
return result
f g h
三个函数
0x5
@staticmethod
def __fmt8(num):
big_hex = '{0:08x}'.format(num)
bin_ver = binascii.unhexlify(big_hex)
result = '{0:08x}'.format(int.from_bytes(bin_ver, byteorder='big'))
return result
@staticmethod
def __block_divide(block, chunks):
result = []
size = len(block) // chunks
for i in range(0, chunks):
result.append(int.from_bytes(block[i * size:(i + 1) * size], byteorder="little"))
return result
@staticmethod
def left_circular_left(k, bits):
bits = bits % (2 ** 32)
k = k % (2 ** 32)
return (k >> (32 - bits) | (k << bits)) % (2 ** 32)
循环左移函数(这里踩了点坑,调试了挺久,具体啥坑忘记了),还有一些工具函数
最后
差不多就这些,代码是参考 md5
源码写的,最终结果一样了
原文始发于微信公众号(二进制科学):猿人学 - app 比赛第一题 python 还原
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论