二刷buu,发现网上的这个题的题解大部分都是动调(可能是我没找到静态),于是想写一篇纯静态分析的文章。
这个题的考点如名字所示,就是一个魔改base64和rc4加密。
首先拖进ida
上面那8个硬编码赋值一看就像key,直接改了个名。
看到结尾的密文对比,顿时有了个大致方向
进入sub_4006B6函数里面,发现是rc4的s盒初始化
传入的参数是放s盒的数组,key和key的长度
没看出来的可以看下这个博客,关于rc4加密的
https://www.cnblogs.com/zwios/p/4196836.html
然后下面的sub_4007DB函数显然就是rc4的crypt函数,查看代码发现没有魔改,很棒。
接下来看sub_4008FA函数
这里从padding和&0x3f等很容易联想到base64(从最后对比的密文也可以很容易联想到),但是这里的base64和正常的base64不一样,因为我们惊奇的发现没有表,而换成了另一种逻辑:
1.把我们的输入(rc4加密过的输入)三个字节一组,变成四个六位的数(这里和base64原理一样)
2.把四个数每个加上61,存入输出的数组之中。
对,就改了第二步,所以我们直接手撕一下就行。
由此,总的程序逻辑清晰了:
1.先将输入rc4加密,key已知。
2.将加密的结果魔改base64加密
3.和密文进行对比
脚本如下:
from base64 import *
import binascii
from Crypto.Util.number import *
duibi="Z`TzzTrD|fQP[_VVL|yneURyUmFklVJgLasJroZpHRxIUlH\\vZE="
# for i in range(len(duibi)-1):
# print(hex(ord(duibi[i])-61),end=",")#得到shuru
shuru=[0x1d,0x23,0x17,0x3d,0x3d,0x17,0x35,0x7,0x3f,0x29,0x14,0x13,0x1e,0x22,0x19,0x19,0xf,0x3f,0x3c,0x31,0x28,0x18,0x15,0x3c,0x18,0x30,0x9,0x2e,0x2f,0x19,0xd,0x2a,0xf,0x24,0x36,0xd,0x35,0x32,0x1d,0x33,0xb,0x15,0x3b,0xc,0x18,0x2f,0xb,0x1f,0x39,0x1d,0x8,0]
def four_to_three(a1,a2,a3,a4):
return (a1<<18)|(a2<<12)|(a3<<6)|a4
for i in range(0,len(shuru),4):
temp=four_to_three(shuru[i],shuru[i+1],shuru[i+2],shuru[i+3])
a1=temp>>16
a2=(temp>>8)&0xff
a3=(temp)&0xff
print(hex(a1)[2:].rjust(2,'0'),end="")
print(hex(a2)[2:].rjust(2,'0'), end="")
print(hex(a3)[2:].rjust(2,'0'), end="")
data1="7635fdf57d47fe95137a26593fff31a1857c63026ebd936a3e4d8dd727732d5ecc62f2dfe5d2"
def rc4_crypt(text,key):
textlen=len(text)
keylen=len(key)
ciper=[]
count=0
s=list(range(256))
for i in range(256):
count=(count+s[i]+key[i%keylen])%256
s[i],s[count]=s[count],s[i]
i=0
j=0
for m in range(textlen):
i=(i+1)%256
j=(j+s[i])%256
s[i],s[j]=s[j],s[i]
k=s[(s[i]+s[j])%256]
ciper.append(k^text[m])
ciper_text=''.join("%02x"%i for i in ciper)
return ciper_text.upper()
if __name__ == "__main__":
data = '7635fdf57d47fe95137a26593fff31a1857c63026ebd936a3e4d8dd727732d5ecc62f2dfe5d2'
key = '1020303020201040'
print()
print("rc4 result:", rc4_crypt(binascii.a2b_hex(data), binascii.a2b_hex(key.upper())))
print(long_to_bytes(0x666C61677B65313061646333393439626135396162626535366530353766323066383833657D))
这里由于密文最后有=,所以我们需要在shuru数组最后加一个0作为padding,然后丢进rc4加密。加密的结果去掉最后的俩0就行。
有不对的地方希望师傅们提出来,一定改正