CrackMe-004

发布于 2023-04-13  71 次阅读


查壳:

image20210214144109107.png

拖进OD:

image20210214144226090.png

典型的Delphi程序,运行一下试试,可以看到有一个大的框,按了没啥反应

image20210214144024785.png

0x01 整体流程分析

拖进IDA:

image20210214152332404.png

定位该字符串:

image20210214152510986.png

既然是Delphi的程序,用Darkde4反编译试试:

image20210214153746922.png

双击TForm1:

image20210214154559083.png

可以看到运行程序中间的位置是一个大按钮,该按钮存在两个事件:

  • Panel1Click
  • Panel1DblClick
image20210214154850804.png

来到过程,定位这两个事件的RVA:

  • Panel1DblClick -> 0x457E7C
  • Panel1Click -> 0x457FB8
image20210214155344865.png

来到FormCreate事件,对于一个Delphi程序的窗口程序,首先会先通过FormCreate创建窗体:

image20210215160535650.png
image20210215160816154.png

这里都调用了unknown_libname_29函数对字符串进行了处理,这里大概可以知道是将字符串分别复制到a1 + 784a1 + 788的位置。

0x02 破解注册码

载入OD,定位到上面分析到的两个事件的RVA,下断点,然后输入用户名和注册码,点击中间的按钮,程序成功停在0x457FB8,并且在该函数中存在字符串“恭喜恭喜,注册成功”,说明该位置应该是破解的位置:

image20210214161605595.png

这里是一个循环,总共进行19循环:

image20210215175707749.png

在该循环结束后,会有一个cmp加jnz,说明该位置应该就是关键跳,注意到后面还有一个循环,所以可以将jnz跳转的位置转到0045803D,或者直接nop填充该位置的跳转也可:

image20210215101607980.png
image20210215101632814.png

nop掉之后直接点中间的框就可以了:

image20210215101914766.png

继续注册码算法破解:

经过19次循环之后:

image20210215180019016.png

最终可以发现得到36user1218这样一个字符串,转成表达式:

str(ord(str(strlen(user)))) + user + str(18)

最终会将esi+0x30c指向的值与0x85进行对比:

image20210215180333169.png

那么就需要去找到这个位置的值是在哪里赋予的:

仔细查看双击事件和单击事件,可以发现GetText拿到的都是用户名而不是注册码,说明注册码在这两个事件之前就已经验证过了,在循环体中似乎也没有对于esi+0x30c这个位置进行赋值,说明该位置的值应该在双击事件之前就已经执行了,重新回到DarkDe4,找事件,通过之前的练习应该也能发现,当按钮点击之后,会通过用户名去生成对应的注册码,再与输入的注册码进行对比,这里也一样,只不过这里的事件是在输入注册码的时候,程序就会不断的调用chkcode事件对输入的注册码进行校验,所以我们直接定位该函数的RVA,下断点:

image20210215210434230.png
image20210215210510679.png

输入完用户名之后,点击注册码,程序卡在该函数的起始位置,说明chkCode进行校验了:

image20210215210641040.png

往下跟可以看到,进行了StrCat

image20210215211010240.png

重新输入一个不同的用户名:test

ebx+0x2F8的值为4,但该函数中并未存在对该位置进行写入的指令

image20210216190508819.png

这里的内存地址是会变化的,所以无法直接设置硬件访问断点,那么就只能设置条件断点:

image20210216191616695.png

0x04 编写注册机

还是之前的注册模板,修改一下生成注册码的位置就可以了:

关键源码:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'main.py'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.

import sys
import random
import string
from PyQt5.QtWidgets import QApplication, QMainWindow
from crackMe04 import Ui_MainWindow


class MyMainWindow(QMainWindow, Ui_MainWindow):
   pre_serial = '黑头Sun Bird'
   med_serial = 'dseloffc-012-OK'
   name = ''
   serial = ''

   def __init__(self, parent=None):
       super(MyMainWindow, self).__init__(parent)
       self.setupUi(self)
       self.pushButton.clicked.connect(self.generate_name_serial)

   def generate_name(self):
       return ''.join(random.sample(string.ascii_letters + string.digits, random.randint(4,10)))

   def generate_serial(self, name):
       return self.pre_serial + str(len(name) + 5) + self.med_serial + name

   def generate_name_serial(self):
       self.name = self.generate_name()
       self.serial = self.generate_serial(self.name)
       self.textEdit.setText(self.name)
       self.textEdit_2.setText(self.serial)


if __name__ == '__main__':
   app = QApplication(sys.argv)
   myWin = MyMainWindow()
   myWin.show()
   sys.exit(app.exec_())
image20210216141648791.png
image20210216141724495.png