【软件安全实验2022】验证码——1

exeinfo 查壳,没啥问题

image.png

打开 IDA,查找字符串

image.png

其中这一项比较可疑,形式一样,进入查看

image.png

image.png

进入,A 键整理字符串

image.png

整理好后是这样

image.png

X 键查看交叉引用

image.png

运气不错!进入

image.png

尝试 Tab 键转换成类 C 语言,因未定义函数,失败。

image.png

到起始位置,C 键转换成 code,后 P 键转换成函数

image.png

image.png

image.png

这时就可以 Tab 键转换成类 C 语言,是函数 sub_40243A

image.png

this 类型明显不是 char**,应该是个句柄结构体指针,更换类型

image.png

image.png

IDA 帮我们分析好了,强强

image.png

观察这几部分,应该是个全局变量的数组

image.png

双击进入

image.png

换成数组

image.png

image.png

N 键重命名

image.png

image.png

ESC 键返回

image.png

Graph View 别扭,换成 Text View,再在函数区域按 Tab

image.png

名字不对的话可以按 N 刷新

image.png

看着烦,隐藏了

image.png

发现里面没有加密函数,对 global_passwd 查看交叉引用,发现函数 sub_401F60

image.png

同样分析,先更换类型

image.png

函数 sub_401F60 关键代码如下,其中有生成 global_passwd 的关键部分

global_passwd程序开始运行时的时间、位置、计算机名称有关

GetLocalTime(&this->systemtime64);

v2 = this->systemtime64.wHour + this->systemtime64.wDay;
weekday = this->systemtime64.wDayOfWeek;
month = this->systemtime64.wMonth;
nSize = 256;
global_passwd[0] = this->systemtime64.wYear + month + weekday + 2 * v2;
GetComputerNameA(computerName, &nSize);
v5 = 0;
if (strlen(computerName))
{
    v6 = global_passwd[1];
    do
    {
        v7 = computerName[v5++];
        v6 += this->systemtime64.wMonth + v7;
        global_passwd[1] = v6;
    } while (v5 < strlen(computerName));
}
GetModuleFileNameA(0, Filename, 0x100u);
for (i = 0; i < strlen(Filename); ++i)
    global_passwd[2] = this->systemtime64.wHour * (global_passwd[1] + Filename[i]);

而对于比较难看懂的第四部分的验证,在于函数 sub_402340 中,其中有

(A= dword ptr -20h)
mov     [esp+30h+A], 67452301h
mov     [esp+30h+A+4], 0EFCDAB89h
mov     [esp+30h+A+8], 98BADCFEh
mov     [esp+30h+A+12], 10325476h

经搜索得 67452301h,0EFCDAB89h,98BADCFEh,10325476h 均为 MD5 中使用的函数,经进一步分析,得出函数行为就是 MD5!

最终,验证码的主体逻辑代码如下,其中

  CWnd::UpdateData(1);                          // 刷新输入数据
  strcpy(passwd, this->pchar7C);                // 复制到String
  passwd[19] = 0;                               // 末尾置'0'
  v6 = global_passwd[0];
  passwd[4] = 0;                                // 删除第一个'-'
  passwd[9] = 0;                                // 删除第二个'-'
  passwd[14] = 0;                               // 删除第三个'-'
  passwd_1 = strtol(passwd, &EndPtr, 16);       // 第一部分转成数值
  passwd_2 = strtol(&passwd[5], &EndPtr, 16);   // 第二部分转成数值
  passwd_3 = strtol(&passwd[10], &EndPtr, 16);  // 第三部分转成数值
  strtol(&passwd[15], &EndPtr, 16);
  a1[0] = passwd[15];
  a1[1] = 0;
  md5(a1, strlen(a1), v8);
  if ( passwd_1 == v6
    && (CWnd::MessageBoxA(this, "恭喜你!序列号第1部分正确!", 0, 0), passwd_2 == (global_passwd[1] >> 8))
    && (CWnd::MessageBoxA(this, "恭喜你!序列号第2部分正确!", 0, 0), passwd_3 == ((global_passwd[0] + global_passwd[2]) >> 8))
    && (CWnd::MessageBoxA(this, "恭喜你!序列号第3部分正确!", 0, 0), v8[3] == 0x69772661)
    && passwd[16] == 'F'
    && passwd[17] == 'F'
    && passwd[18] == '0' )
  {
    result = CWnd::MessageBoxA(this, "恭喜你!序列号完全正确!", 0, 0);
  }

分析得 python 脚本

import hashlib
import datetime
import socket
import os

time = datetime.datetime.now()  # 获取当前时间
year = time.year
month = time.month
weekday = time.weekday() + 1  # 星期一应该对应'1',故加一
hour = time.hour
day = time.day

passwd = [0, 0, 0, 0]

passwd[0] = year + month + weekday + 2 * (hour + day)

computerName = socket.gethostname().upper()  # 获取计算机名,需要大写
for ch in computerName:
    passwd[1] += month + ord(ch)

fileFlag = False
filePath = ''
for root, dirs, files in os.walk(os.getcwd(), topdown=True):
    if 'DemoD2022.exe' in files:
        filePath = root + '\\DemoD2022.exe'
        fileFlag = True
        break
if fileFlag == False:
    print('未找到 DemoD2022.exe ,请放至同一文件夹下')
    exit(0)
for ch in filePath:
    passwd[2] = hour * (passwd[1] + ord(ch))

for i in range(255):
    m = hashlib.md5()
    m.update(i.to_bytes(1, 'big'))
    if m.hexdigest()[24:] == '69772661':
        print(
            ('{:04X}-{:04X}-{:04X}-{}FF0').format(passwd[0], passwd[1] >> 8,
                                                  (passwd[0] + passwd[2]) >> 8,
                                                  chr(i)))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值