2022年HGAME中REVERSE的Flag Checker
照例下载附件:
.
.
APK 文件,运行不了,照例扔入 JEB 中查看代码:
.
.
既然是 RC4 加密,那么直接搬上解密代码,结果发现解码错误:
.
.
那就修改编码为 Unicode-escape 编码,正确代码如下:(相关编码细节可以查看另一篇博客)
# -*- coding: utf-8 -*-
import base64
def get_message():
print("输入你的信息: ")
s=input()
return s
def get_key():
print("输入你的密钥: ")
key=input()
if key=='':
key="不要输入空的 key 值"
return key
def init_box(key):
"""
S盒
"""
s_box=list(range(256)) #我这里没管秘钥小于256的情况,小于256应该不断重复填充即可,这里完成了 C 实现中的 for(i=0;i<256;i++) prc4->s_box[i] = i;
j=0
for i in range(256):
j=(j+s_box[i] + ord(key[i % len(key)])) % 256 #这里把 C 实现中的 prc4->t_box[i] = key[i % keylen];和j=(j+prc4->s_box[i]+prc4->t_box[i])%256;合并在了一起。
s_box[i],s_box[j] = s_box[j],s_box[i]
#print(type(s_box)) #可以输出 s_box 来看是否随机混乱的
return s_box
def ex_encrypt(plain,box,mode):
"""
利用PRGA生成秘钥流并与密文字节异或,加解密同一个算法
"""
if mode == '2':
while True:
c_mode=input("输入你的解密模式:base64 or ordinary\n")
if c_mode == 'base64':
plain=base64.b64decode(plain)
plain=bytes.decode(plain,'unicode-escape') #因为返回的是解码过的 bytes,所以需要再用 decode 解码成字符串。
break
elif c_mode == 'ordinary':
break
else:
print("输入不合法,请重新输入")
continue
res=[]
i=j=0
for s in plain: #与 C 实现无太大差异
i=(i+1)%256
j=(j+box[i])%256
box[i],box[j]=box[j],box[i]
t=(box[i]+box[j]) % 256
k=box[t]
res.append(chr(ord(s)^k))
cipher="".join(res)
#print(cipher)
#根据选择进行输出,至于是明文还是密文得看用户决定
if mode == '1':
# 化成可视字符需要编码
print("加密后的输出(没经过任何编码)")
print(cipher)
# base64的目的也是为了变成可见字符
print("base64后的编码")
print(str(base64.b64encode(cipher.encode('utf-8')),'utf-8'))
if mode == '2':
print("解密后的密文")
print(cipher)
def get_mode():
print("请选择加密或者解密")
print("1.Encrypt")
print("2.Decrypt")
mode = input()
if mode == '1': #加密解密虽同源,但是由于不能直接用 =='1' or '2',所以还是得分开写
message = get_message()
key = get_key()
box = init_box(key)
ex_encrypt(message,box,mode)
elif mode == '2': #由于异或运算的对合性,RC4加密解密使用同一套算法。
message = get_message()
key = get_key()
box = init_box(key)
ex_encrypt(message,box,mode)
else:
print("输入有误! ")
if __name__ == '__main__':
while True:
get_mode()
.
.
涉及编码问题的都比较麻烦,上面的代码有缺陷,不可以反向加密,所以可以直接选择用 byte 流的方式加密解密,就不用涉及编码了.
.
.
第一种,直接用 python 封装库,正向反向都可以:
from Crypto.Cipher import ARC4 as rc4cipher
import base64
def rc4_algorithm(encrypt_or_decrypt, data, key1):
if encrypt_or_decrypt == "encrypt":
key = bytes(key1, encoding='utf-8')
enc = rc4cipher.new(key)
res = enc.encrypt(data.encode('utf-8'))
res=base64.b64encode(res)
res = str(res,'utf8')
return res
elif encrypt_or_decrypt == "decrypt":
data = base64.b64decode(data)
#print(data)
#print(str(data,'utf-8'))
key = bytes(key1, encoding='utf-8')
enc = rc4cipher.new(key)
res = enc.decrypt(data)
res = str(res,'utf8')
return res
if __name__ == "__main__":
data = 'hgame{weLC0ME_To-tHE_WORLD_oF-AnDr0|D}'
key = 'carol'
print(rc4_algorithm('encrypt',data,key))
res ='mg6CITV6GEaFDTYnObFmENOAVjKcQmGncF90WhqvCFyhhsyqq1s='
print(rc4_algorithm('decrypt', res, key))
.
.
第二种,C 语言版,base64 解码后直接生成 byte 字节,然后进行解密:
import base64
c="mg6CITV6GEaFDTYnObFmENOAVjKcQmGncF90WhqvCFyhhsyqq1s="
c=base64.b64decode(c)
arr=[]
for i in c:
arr.append(ord(i))
print(arr)
#[154, 14, 130, 33, 53, 122, 24, 70, 133, 13, 54, 39, 57, 177, 102, 16, 211, 128, 86, 50, 156, 66, 97, 167, 112, 95, 116, 90, 26, 175, 8, 92, 161, 134, 204, 170, 171, 91]
#include<stdio.h>
void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k)
{
int i = 0, j = 0;
char k[256] = { 0 };
unsigned char tmp = 0;
for (i = 0; i < 256; i++) {
s[i] = i;
k[i] = key[i % Len_k];
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + k[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
}
void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key, unsigned long Len_k) //加解密
{
unsigned char s[256];
rc4_init(s, key, Len_k);
int i = 0, j = 0, t = 0;
unsigned long k = 0;
unsigned char tmp;
for (k = 0; k < Len_D; k++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
t = (s[i] + s[j]) % 256;
Data[k] = Data[k] ^ s[t];
}
}
void main()
{
unsigned char key[] = "carol";
unsigned long key_len = sizeof(key) - 1;
unsigned char data[] = { 154, 14, 130, 33, 53, 122, 24, 70, 133, 13, 54, 39, 57, 177, 102, 16, 211, 128, 86, 50, 156, 66, 97, 167, 112, 95, 116, 90, 26, 175, 8, 92, 161, 134, 204, 170, 171, 91 };
rc4_crypt(data, sizeof(data), key, key_len);
for (int i = 0; i < sizeof(data); i++)
{
printf("%c", data[i]);
}
printf("\n");
return;
}
//hgame{weLC0ME_To-tHE_WORLD_oF-AnDr0|D}
.
.
解毕!
敬礼!