新手破解练习Crackme160之159 - Torn@do.2

  1. 脱壳
    这个程序有壳, 需要先脱壳, ESP定律手动脱壳~ OD载入程序, F8运行一次, 来到第二行, 此时ESP值变红, 右键这个红值, 选择"HW break [ESP]"下好硬件断点, F9运行19次来到00401F096 jmp eax这里(中间也都是到这里), F8进入程序区域00403560, 删除硬件断点(菜单->调试->硬件断点), 00403560这行右键使用OllyDump, 此时用OllyDump的方式2脱壳成功~

  2. 正常破解
    OD重新载入脱壳后程序, 搜索界面找到成功关键词定位到0040148D处, 由此可向上找按钮事件入口004021D5处, 可下断点, 接着便一步步向下跟踪对应算法~
    1). 00401D02处可得算法:
    s[0] ^ 0x54 = 0x1D
    s[1] ^ 0x49 = 0xD
    s[2] ^ 0x44 = 0x7
    s[3] ^ 0x39 = 0xD
    s[4] ^ 0x39 = 0x9
    反向运算得系列号0~4位为: IDC40
    2). 00401D36处可得算法:
    s[6] ^ 0x54 = 0x11
    s[7] ^ 0x52 = 0x6
    s[8] ^ 0x45 = 0x7
    s[9] ^ 0x53 = 0x1F
    反向运算得系列号6~9位为: ETBL
    3). 00401D52处可得算法:
    取当前时间=>month * day + hour * minute - 0x20 + year = time2
    计算结果与系列号的后4位进行对比(也就是后4位即为这个时间值)
    4). 00401D80处获取注册时间 这个需要读取注册表, 值为time1
    5). 00401DA8处用户名与公司名的验证
    sum = 用户名循环每一位*2601之和 + 公司名循环每一位之和
    sum1 = ((sum * 11) ^2 + CheckRegOwner[0]) * 111998
    code = (long) (sum1 - sin(sum1) * 1999)
    所以最终的系列号为: IDC40-ETBL-code-time1-time2 (中间的-号可以任意)
    由于系列号跟时间有关系的, 所以生成了系列号后需要快速注册~
    上面需要是分析完了, 注册时间部分由于需要注册表操作, 放弃了, 所以没有实际注册成功过~

下面是solly大佬的注册机代码:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <windows.h>
 
union CBData{
        DWORD n;
        byte buffer[256];
};
 
CBData readKey(HKEY hKey, char * path, char * key);
void getRegInfo();
void getPart1();
void getPart2();
long getRegTimeStamp(int index);
long getCheckRegOwner();
long getCheck(char * name, char * company, int index);
void getCurrDateTime(int index);
 
bool testSoftICE95();
bool testSoftICENT();
 
char sn[48];
CBData data;
long nFirstInstallDateTime = 0;
long nLenOfFirstInstallDateTime = 0;
char sFirstInstallDateTime[128];
char RegisteredOwner[128];
char RegisteredOrganization[128];
char ProductId[128];
 
int main(int argc, char** argv) {
	memset(sn, 0, 48);
	memset(sFirstInstallDateTime, 0, 128);
	memset(RegisteredOwner, 0, 128);
	memset(RegisteredOrganization, 0, 128);
	memset(ProductId, 0, 128);
	 
	getRegInfo();
	 
	getPart1();
	sn[5] = '-';
	
	getPart2();
	sn[10] = '-';
	 
	char name[]    = "solly88";
	char company[] = "ite company";
	int n = getCheck(name, company, 11);
	
	sn[10+n+1] = '-';
	
	int m = getRegTimeStamp(10+n+2);
	 
	sn[10+n+2+m] = '-';
	 
	/// 最后4字节为当前时间检查
	getCurrDateTime(10+n+3+m);
	 
	printf("\n SN = %s\n", sn);
	system("pause"); 
	return 0;
}
 
void getPart1() {
    sn[1] = 0x0D ^ 0x49;
    sn[2] = 0x07 ^ 0x44;
    sn[3] = 0x0D ^ 0x39;
    sn[0] = 0x1D ^ 0x54;
    sn[4] = 0x09 ^ 0x39;
}
 
void getPart2() {
    sn[7] = 0x06 ^ 0x52;
    sn[8] = 0x07 ^ 0x45;
    sn[9] = 0x1F ^ 0x53;
    sn[6] = 0x11 ^ 0x54;
}
 
/**
 
***/
/// FirstInstallTime
long getRegTimeStamp(int index) {
        /// 0040BF90:  1702516
    //long a = 1702505;
    ////
    //long FirstInstallDateTime = 1702516; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win10
    //long FirstInstallDateTime = 6617404; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win98
    //long FirstInstallDateTime = 6682940; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win98_unpacked
    long FirstInstallDateTime = nFirstInstallDateTime; /// 正常时是一个 Timestamp
     
    long a = FirstInstallDateTime - tanh(FirstInstallDateTime) * 11.0;  /// 当在win10下取的是地址时,这里是固定值 1702505
              
    //char str_a[8];
    sprintf(sFirstInstallDateTime, "%d", a);
    long n = strlen(sFirstInstallDateTime);
    for(int i=0; i<n; i++ ) {
            sn[index + i] = sFirstInstallDateTime[i];
        }
         
        return n;
}
 
long getCheckRegOwner() {  // Proc_00401590 和 Proc_00401540
        long sum1 = 0;
        long sum2 = 0;
        long n = strlen(RegisteredOwner);
        for(int i=1; i<n; i++) {
                sum1 += i*2;
                sum2 += RegisteredOwner[i-1];
        }
        //printf("check reg owner: %d - %d\n", sum1, sum2);
         
        return sum1 ^ sum2;
}
 
long getCheck(char * name, char * company, int index) {  /// Proc_004015E0
 
        long checkbase = getCheckRegOwner();
         
        long sum = 0;
        int n = strlen(name);
        for(int i=0; i<n-1; i++) {
                sum += name[i] * 2601;
        }
        int m = strlen(company);
        for(int i=0; i<m-1; i++) {
                sum += company[i];
        }
         
        double x = sum * 11;
        int code1 = (long)sqrt(x);
        ////
        //printf("check code1: %d, %d\n", sum, code1);
        long a = code1 + checkbase;
        long c = a * 111998;
        double y = c - sin(c) * 1999.0;
        long code2 = (long)y;
         
        //printf("check code2: %d\n", code2);
        char code_str[12];
        sprintf(code_str, "%d", code2);
        int len = strlen(code_str);
        for(int i=0; i<len; i++) {
                sn[index+i] = code_str[i];
        }
         
        return len;
}
 
bool testSoftICE95() {
        HANDLE h = CreateFile("\\\\.\\SICE",
                              GENERIC_READ|GENERIC_WRITE,
                                                  FILE_SHARE_READ|FILE_SHARE_WRITE,
                                                  NULL, OPEN_EXISTING,
                                                  FILE_ATTRIBUTE_NORMAL, NULL);
        if(h != INVALID_HANDLE_VALUE) {
                CloseHandle(h);
                return true;
        }
         
        return false;
}
 
bool testSoftICENT() {
        HANDLE h = CreateFile("\\\\.\\NTICE",
                              GENERIC_READ|GENERIC_WRITE,
                                                  FILE_SHARE_READ|FILE_SHARE_WRITE,
                                                  NULL, OPEN_EXISTING,
                                                  FILE_ATTRIBUTE_NORMAL, NULL);
        if(h != INVALID_HANDLE_VALUE) {
                CloseHandle(h);
                return true;
        }
         
        return false;
}
 
/// Current date and time
void getCurrDateTime(int index) {
        long a = RegisteredOwner[0];
        time_t timer;
        struct tm * st;
        time(&timer);
        st = localtime(&timer);
        long t = (st->tm_year + 1900) + ((st->tm_mon + 1) * st->tm_mday - a) + st->tm_hour * st->tm_min;
         
        ///// SoftICE 检查,修正时间检查值(基本无用)
        bool isExistsSICE95 = testSoftICE95();
        bool isExistsSICENT = testSoftICENT();
         
        if (isExistsSICE95) {
                t += 0x143;
        }
        if (isExistsSICENT) {
                t += 0x271;
        }
 
        char str_t[12];
        itoa(t, str_t, 10);
        sn[index] = str_t[0];
        sn[index+1] = str_t[1];
        sn[index+2] = str_t[2];
        sn[index+3] = str_t[3];
        ///
        //printf("time: %d-%d-%d %d:%d\n", st->tm_year+1900, st->tm_mon+1, st->tm_mday, st->tm_hour, st->tm_min)       ;
}
 
CBData readKey(HKEY hKey, char * path, char * key) {
        HKEY h = (HKEY)-1;
        DWORD cbData;
        DWORD regType = -1;
 
        data.n = 1;
         
        long s = RegOpenKeyEx(hKey, path, 0, KEY_READ, &h);
        if( s != ERROR_SUCCESS) {
                data.n = -1;
                return data;
        }
         
        s = RegQueryValueEx(h, key, NULL, NULL, NULL, &cbData);
        if(s == ERROR_SUCCESS) {
                RegQueryValueEx(h, key, NULL, & regType, data.buffer, &cbData);
        }
         
        RegCloseKey(h);
         
        return data;
}
 
void getRegInfo() {
        char subKey[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion";
        char key1[] = "FirstInstallDateTime";
        char key2[] = "RegisteredOwner";
        char key3[] = "RegisteredOrganization";
        char key4[] = "ProductId";
        CBData cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key1);
        nFirstInstallDateTime = cb.n;
        struct tm * tm_reg = localtime((time_t *)&nFirstInstallDateTime);
        sprintf(sFirstInstallDateTime, "%lu", nFirstInstallDateTime);
        nLenOfFirstInstallDateTime = strlen(sFirstInstallDateTime);
        printf(" DateTime: %d-%d-%d %d:%d:%d\n", tm_reg->tm_year + 1900, tm_reg->tm_mon + 1,
                                tm_reg->tm_mday, tm_reg->tm_hour, tm_reg->tm_min, tm_reg->tm_sec);
        printf("Timestamp: %d,  len=%d\n", nFirstInstallDateTime, nLenOfFirstInstallDateTime);
        ////
        cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key2);
        strcpy(RegisteredOwner, (char *)cb.buffer);
        ////
        cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key3);
        strcpy(RegisteredOrganization, (char *)cb.buffer);
        ////
        cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key4);
        strcpy(ProductId, (char *)cb.buffer);
         
        printf("             ProductId: %s\n", ProductId);
        printf("       RegisteredOwner: %s\n", RegisteredOwner);
        printf("RegisteredOrganization: %s\n", RegisteredOrganization);
}

 
 
 
这是160个软件part1
这是160个软件part2

1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载

新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~

下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~
OD界面布局

posted @ 2024-08-27 16:02  hankerstudio  阅读(31)  评论(0)    收藏  举报