多么经典的窗口程序的反汇编代码,跟上次华科大比赛的flag自动机简直一模一样,于是我就想想上次一样,通过想窗口发送消息让窗口把flag给我们
感觉MSG==1比较有可能,但是问题来了,打开窗口程序是一个全屏的,而且进行任何操作都会触发关闭窗口的指令,我们就要对程序作出修改,首先改掉全屏大小
去搜一下CreateWindow的函数原型就知道,v4是宽度,System是高度,然后函数GetSystemMetrics(1)
和GetSystemMetrics(0)
分别是填满整个宽和整个高
修改这个位置的16进制可以更改参数,但是怎么修改他还是全屏
.text:004010AE 6A 01 push 1 ; nIndex
.text:004010B3 6A 00 push 0 ; nIndex
于是我就把关闭窗口的指令全部给NOP掉然后通过按win键唤出任务栏打开c语言程序
把这些全部NOP掉,操作和上次的falg自动机操作方法一模一样
链接flag自动机
然后c语言代码也和上次那题一样
#include <windows.h>
#include <stdio.h>
int main(void){
HWND target = NULL;
target = FindWindowW(L"matrix",0);
if (target == NULL){
printf("error!");
return -1;
}
//printf("0x%x", target);
PostMessageW(target,0x1, NULL,NULL );
return 0;
}
然后还是我太天真了,直接卡死程序,然后就只能分析窗口处理程序了
在FindCrypto插件里面找到了base64密码表,然后查看引用,发现了是RC4,利用加密后的数字作为base表的索引,然后返回
经过一晚上的努力,RC4解密出来了,代码写的非常丑陋
#字符串index返回该字符在字符串中的索引
code = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
key = (b'Triglavian' * 10)[:64]
#生成T盒
T=[]
for i in key:
T.append(code.index(i))
#S盒
S=list(range(64))
#置换
j=0
for i in range(64):
j=(j+S[i]+T[i])%64
tmp=S[i]
S[i]=S[j]
S[j]=tmp
#密钥流
i=j=0
#密文
data=b'20c1LOP2FnBOCMhPbCdtXTHmpgoK7g1sPN0KCcaBs3sWx/5Bob1t6IJaahW6SUGpTW11DmhJGeTj3UCSPCOZYaLw9qmg80kN56XF+dNhBYlfKbWqwSKJl+zTBvH0yBLDy7nwJ1W/SeBW+LaUV1Dq4FRnogzD5FOHNknyfyMerA3o5lgRq03f2M5C7ixuJ6WK'
k=[]
for h in range(len(data)):
i = (i + 1) % 64
j = (j + S[i]) % 64
tmp=S[i]
S[i]=S[j]
S[j]=tmp
k.append(S[(S[i] + S[j]) % 64])
#data不是加密后的密文是加密后的密文作为base表的索引转化成base表对应的字符
for i in range(len(data)):
print(chr(code[((code.index(data[i]))^k[i])%64]),end='')
#flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/flag/SECRETTriglavianModifiyM1n1RC4StreamCipher/
不魔改的RC4加密流程
//生成S盒和T表
for(i=0;i<256;i++)
{
S[i]=i;
T[i]=K[i mod keylen];
}
//置换
j=0;
for(i=0;i<256;i++)
{
j=(j+S[i]+T[i])%256;
swap(S[i],S[j]);
}
//得到密钥流,顺便异或加密
i=j=0;
for(h=0;h<datalen;h++)
{
i=(i+1)%256;
j=(j+S[i])%256;
swap(S[i],S[j]);
t=(S[i]+S[j])%256;
k=S[t];
D[h]^=k;
}