160crackme
160CrackMe
看视频的笔记
https://space.bilibili.com/514311388/channel/collectiondetail?sid=46524
003-Cruehead-CrackMe-3
查看代码
#include <Windows.h>
#include <memory>
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
const char* lpszFile = "D:\\crack\\New160CrackMe\\003-Cruehead-CrackMe-3\\CRACKME3.KEY";
char key[19];
strcpy_s(key, sizeof(key), "abcdefghijklmnopqr");
INT32 iSum = 0;
for (int ebx = 0x41, i = 0; ebx < 0x4f; ++ebx, ++i)
{
int iTmp = key[i];
iTmp ^= ebx;
printf("%d : %x %x %x\n", i, key[i], ebx, iTmp);
key[i] = iTmp;
iSum += key[i];
}
iSum ^= 0x12345678;
printf("iSum: %x\n", iSum);
char* lpcSum = static_cast<char*>(static_cast<void*>(&iSum));
for (int i = 0; i < 4; ++i)
{
memcpy(key + 14 + i, lpcSum + i, 1);
printf("%x\n", static_cast<byte>(key[14 + i]));
}
key[18] = '\0';
for (int i = 0; i < 18; ++i)
{
printf("%x", static_cast<byte>(key[i]));
}
HANDLE f = CreateFile(lpszFile,
GENERIC_READ | GENERIC_WRITE,
0,
nullptr,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
nullptr);
if (f == INVALID_HANDLE_VALUE) {
cout << "open file failed!" << endl;
CloseHandle(f);
return 0;
}
WriteFile(f, "abcdefghijklmn", 14, nullptr, nullptr);
WriteFile(f, key + 14, 4, nullptr, nullptr);
CloseHandle(f);
return 0;
}
007-reg
在调试过程中可以看见真正的注册码,但是生成注册码的方法很复杂,可能用到了md5之类的方法
不易做出注册机,或许可以通过程序从软件的内存中读出注册码
与通用软件通过用户名和校验码验证的方式相同,值得认真分析
Delphi 编写,运行发现软件将输入的UserName和SN写入一个文本文件,并重命名为 reg.dll
0045D498 /. 55 push ebp
0045D499 |. 8BEC mov ebp,esp
0045D49B |. 33C9 xor ecx,ecx
0045D49D |. 51 push ecx
0045D49E |. 51 push ecx
0045D49F |. 51 push ecx
0045D4A0 |. 51 push ecx
0045D4A1 |. 51 push ecx
0045D4A2 |. 51 push ecx
0045D4A3 |. 53 push ebx
0045D4A4 |. 56 push esi
0045D4A5 |. 8BF0 mov esi,eax
0045D4A7 |. 33C0 xor eax,eax
0045D4A9 |. 55 push ebp
0045D4AA |. 68 A9D54500 push Reg.0045D5A9
0045D4AF |. 64:FF30 push dword ptr fs:[eax]
0045D4B2 |. 64:8920 mov dword ptr fs:[eax],esp
0045D4B5 |. 8D45 FC lea eax,[local.1]
0045D4B8 |. BA C0D54500 mov edx,Reg.0045D5C0 ; 您的有效期至
0045D4BD |. E8 366FFAFF call Reg.004043F8 ; # 取出字符串放入eax中的地址
0045D4C2 |. 8D45 F8 lea eax,[local.2]
0045D4C5 |. BA D8D54500 mov edx,Reg.0045D5D8 ; 未注册
0045D4CA |. E8 296FFAFF call Reg.004043F8
0045D4CF |. B8 E8D54500 mov eax,Reg.0045D5E8 ; reg.dll
0045D4D4 |. E8 FBB3FAFF call Reg.004088D4 ; # eax指向文件名地址,测试文件是否存在
0045D4D9 |. 84C0 test al,al
0045D4DB |. 0F84 AD000000 je Reg.0045D58E ; # al为0,文件不存在
0045D4E1 |. B2 01 mov dl,0x1
0045D4E3 |. A1 B4244100 mov eax,dword ptr ds:[0x4124B4] ; ─A
0045D4E8 |. E8 F360FAFF call Reg.004035E0
0045D4ED |. 8BD8 mov ebx,eax
0045D4EF |. BA E8D54500 mov edx,Reg.0045D5E8 ; reg.dll
0045D4F4 |. 8BC3 mov eax,ebx
0045D4F6 |. 8B08 mov ecx,dword ptr ds:[eax]
0045D4F8 |. FF51 68 call dword ptr ds:[ecx+0x68] ; # 猜测此处是读文件
0045D4FB |. 8D4D F4 lea ecx,[local.3]
0045D4FE |. BA F8D54500 mov edx,Reg.0045D5F8 ; UserName
0045D503 |. 8BC3 mov eax,ebx
0045D505 |. E8 8285FBFF call Reg.00415A8C ; # 读取文件中的UserName
0045D50A |. 8D4D F0 lea ecx,[local.4]
0045D50D |. BA 0CD64500 mov edx,Reg.0045D60C ; SN
0045D512 |. 8BC3 mov eax,ebx
0045D514 |. E8 7385FBFF call Reg.00415A8C ; # 读取文件中的SN
0045D519 |. 8BC3 mov eax,ebx
0045D51B |. E8 F060FAFF call Reg.00403610
0045D520 |. 8B55 F0 mov edx,[local.4]
0045D523 |. 8B45 F4 mov eax,[local.3]
0045D526 |. E8 C9FBFFFF call Reg.0045D0F4 ; # **算法call**
0045D52B |. 84C0 test al,al
0045D52D |. 74 44 je short Reg.0045D573
0045D52F |. 8B45 F0 mov eax,[local.4]
0045D532 |. E8 FDF6FFFF call Reg.0045CC34
0045D537 |. 83C4 F8 add esp,-0x8 ; /
0045D53A |. DD1C24 fstp qword ptr ss:[esp] ; |Arg1 (8-byte)
0045D53D |. 9B wait ; |
0045D53E |. 8D45 E8 lea eax,[local.6] ; |
0045D541 |. E8 A2D4FAFF call Reg.0040A9E8 ; \Reg.0040A9E8
0045D546 |. 8B4D E8 mov ecx,[local.6]
0045D549 |. 8D45 EC lea eax,[local.5]
0045D54C |. 8B55 FC mov edx,[local.1]
0045D54F |. E8 1871FAFF call Reg.0040466C
0045D554 |. 8B45 EC mov eax,[local.5]
0045D557 |. 50 push eax
0045D558 |. 8B86 18030000 mov eax,dword ptr ds:[esi+0x318]
0045D55E |. 8B80 08020000 mov eax,dword ptr ds:[eax+0x208] ; Reg.<ModuleEntryPoint>
0045D564 |. 33D2 xor edx,edx
0045D566 |. E8 5112FDFF call Reg.0042E7BC
0045D56B |. 5A pop edx ; 0019FDA0
0045D56C |. E8 A711FDFF call Reg.0042E718
0045D571 |. EB 1B jmp short Reg.0045D58E
0045D573 |> 8B86 18030000 mov eax,dword ptr ds:[esi+0x318]
0045D579 |. 8B80 08020000 mov eax,dword ptr ds:[eax+0x208] ; Reg.<ModuleEntryPoint>
0045D57F |. 33D2 xor edx,edx
0045D581 |. E8 3612FDFF call Reg.0042E7BC
0045D586 |. 8B55 F8 mov edx,[local.2]
0045D589 |. E8 8A11FDFF call Reg.0042E718
0045D58E |> 33C0 xor eax,eax
0045D590 |. 5A pop edx ; 0019FDA0
0045D591 |. 59 pop ecx ; 0019FDA0
0045D592 |. 59 pop ecx ; 0019FDA0
0045D593 |. 64:8910 mov dword ptr fs:[eax],edx
0045D596 |. 68 B0D54500 push Reg.0045D5B0
0045D59B |> 8D45 E8 lea eax,[local.6]
0045D59E |. BA 06000000 mov edx,0x6
0045D5A3 |. E8 DC6DFAFF call Reg.00404384
0045D5A8 \. C3 retn
0045D5A9 .^ E9 B667FAFF jmp Reg.00403D64
0045D5AE .^ EB EB jmp short Reg.0045D59B
0045D5B0 . 5E pop esi ; 0019FDA0
0045D5B1 . 5B pop ebx ; 0019FDA0
0045D5B2 . 8BE5 mov esp,ebp
0045D5B4 . 5D pop ebp ; 0019FDA0
0045D5B5 . C3 retn
# 算法运行期间可以获得其中的注册码
0045D0F4 $ 55 push ebp ; # 算法 改为 retn
0045D0F5 . 8BEC mov ebp,esp # mov eax,1
0045D0F7 . 83C4 D0 add esp,-0x30 # retn
0045D0FA . 53 push ebx # 即可实现爆破
0045D0FB . 56 push esi
0045D0FC . 57 push edi ; Reg.0045C3E8
0045D0FD . 33C9 xor ecx,ecx
0045D0FF . 894D EC mov dword ptr ss:[ebp-0x14],ecx
0045D102 . 894D D4 mov dword ptr ss:[ebp-0x2C],ecx
0045D105 . 894D D0 mov dword ptr ss:[ebp-0x30],ecx
0045D108 . 894D D8 mov dword ptr ss:[ebp-0x28],ecx
0045D10B . 894D F4 mov dword ptr ss:[ebp-0xC],ecx
0045D10E . 894D F0 mov dword ptr ss:[ebp-0x10],ecx
0045D111 . 8955 F8 mov dword ptr ss:[ebp-0x8],edx
0045D114 . 8945 FC mov dword ptr ss:[ebp-0x4],eax
0045D117 . 8B45 FC mov eax,dword ptr ss:[ebp-0x4]
0045D11A . E8 F176FAFF call Reg.00404810
0045D11F . 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
0045D122 . E8 E976FAFF call Reg.00404810
0045D127 . 33C0 xor eax,eax
0045D129 . 55 push ebp
0045D12A . 68 53D24500 push Reg.0045D253
0045D12F . 64:FF30 push dword ptr fs:[eax]
0045D132 . 64:8920 mov dword ptr fs:[eax],esp
0045D135 . 33DB xor ebx,ebx
0045D137 . 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
0045D13A . E8 E174FAFF call Reg.00404620 ; # 序列号长度 == 16字符
0045D13F . 83F8 10 cmp eax,0x10
0045D142 . 0F85 E3000000 jnz Reg.0045D22B
0045D148 . B8 01000000 mov eax,0x1 # 计数器
0045D14D > 8B55 F8 mov edx,dword ptr ss:[ebp-0x8] # 循环开始
0045D150 . 8A5402 FF mov dl,byte ptr ds:[edx+eax-0x1]
0045D154 . 80C2 D0 add dl,0xD0
0045D157 . 80EA 0A sub dl,0xA
0045D15A . 72 0C jb short Reg.0045D168
0045D15C . 80C2 F9 add dl,0xF9
0045D15F . 80EA 06 sub dl,0x6
0045D162 . 0F83 C3000000 jnb Reg.0045D22B
0045D168 > 40 inc eax
0045D169 . 83F8 11 cmp eax,0x11
0045D16C .^ 75 DF jnz short Reg.0045D14D ; # 循环结束
0045D16E . 33C0 xor eax,eax
0045D170 . 55 push ebp
0045D171 . 68 B0D14500 push Reg.0045D1B0
0045D176 . 64:FF30 push dword ptr fs:[eax]
0045D179 . 64:8920 mov dword ptr fs:[eax],esp
0045D17C . 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
0045D17F . E8 B0FAFFFF call Reg.0045CC34
0045D184 . 83C4 F8 add esp,-0x8 ; /
0045D187 . DD1C24 fstp qword ptr ss:[esp] ; |Arg1 (8-byte)
0045D18A . 9B wait ; |
0045D18B . 8D55 F4 lea edx,dword ptr ss:[ebp-0xC] ; |
0045D18E . B8 6CD24500 mov eax,Reg.0045D26C ; |yymmdd
0045D193 . E8 7CD8FAFF call Reg.0040AA14 ; \Reg.0040AA14
0045D198 . 8D4D F0 lea ecx,dword ptr ss:[ebp-0x10]
0045D19B . 8B55 F4 mov edx,dword ptr ss:[ebp-0xC]
0045D19E . 8B45 FC mov eax,dword ptr ss:[ebp-0x4]
0045D1A1 . E8 3AF4FFFF call Reg.0045C5E0
0045D1A6 . 33C0 xor eax,eax
0045D1A8 . 5A pop edx ; 0019FDA0
0045D1A9 . 59 pop ecx ; 0019FDA0
0045D1AA . 59 pop ecx ; 0019FDA0
0045D1AB . 64:8910 mov dword ptr fs:[eax],edx
0045D1AE . EB 13 jmp short Reg.0045D1C3
0045D1B0 .^ E9 FB68FAFF jmp Reg.00403AB0
0045D1B5 . 33DB xor ebx,ebx
0045D1B7 . E8 5C6CFAFF call Reg.00403E18
0045D1BC . EB 6D jmp short Reg.0045D22B
0045D1BE . E8 556CFAFF call Reg.00403E18
0045D1C3 > 8D55 DC lea edx,dword ptr ss:[ebp-0x24]
0045D1C6 . 8B45 F0 mov eax,dword ptr ss:[ebp-0x10]
0045D1C9 . E8 6EECFFFF call Reg.0045BE3C
0045D1CE . 8D45 DC lea eax,dword ptr ss:[ebp-0x24]
0045D1D1 . 8D55 D8 lea edx,dword ptr ss:[ebp-0x28]
0045D1D4 . E8 D7ECFFFF call Reg.0045BEB0
0045D1D9 . 8B45 D8 mov eax,dword ptr ss:[ebp-0x28]
0045D1DC . 8D55 DC lea edx,dword ptr ss:[ebp-0x24]
0045D1DF . E8 58ECFFFF call Reg.0045BE3C
# ...
008-Afkayas
这个程序是VB写的,其中有太多的无用的call和其他语句,难点是干扰太多。
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name{"wewfe"};
unsigned int iLenName{name.length()};
int iTmp = iLenName * 0x17CFB;
iTmp += name[0];
cout << "AKA-" + to_string(iTmp) << endl;
return 0;
}
009-Boonz-KeygenMe#1
#include <memory>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main()
{
string name{ "ergae345455h4reg" };
cout.setf(ios::uppercase);
unsigned int iNum11 = 0;
for (auto ch : name) {
unsigned int iTmp = ch;
iTmp -= 0x19;
iNum11 -= iTmp;
}
unsigned int iNum21{ iNum11 };
iNum21 = iNum11 * iNum11 * iNum11;
// --------这是一个常量 0x41720F48
//unsigned int iNum31{ iNum11 };
//iNum31 = static_cast<unsigned int>(0x40E0F8 * 0x40E0F8);
//iNum31 -= 0x40E0F8;
//cout << hex << iNum31 << endl;
char szAns[100];
sprintf_s(szAns, "Bon-%lX-%lX-41720F48", iNum11, iNum21);
cout << szAns << endl;
}
012-ACG-crcme1
#include <Windows.h>
#include <memory>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
UINT32 xorNum[0xC] = { 0x168 ,0x160 ,0x170 ,0xEC ,0x13C ,0x1CC ,0x1F8 ,0xEC ,0x164 ,0x1F8 ,0x1A0 ,0x1BC };
UINT32 rol(UINT32 uiNum, int iSize)
{
UINT32 res{ uiNum << iSize };
res |= (uiNum >> (32 - iSize));
return res;
}
UINT32 ror(UINT32 uiNum, int iSize)
{
UINT32 res{ uiNum >> iSize };
res |= (uiNum << (32 - iSize));
return res;
}
string getKeyFileContent()
{
char str[0xD];
str[0xC] = '\0';
for (int i = 0; i < 0xC; ++i)
{
UINT32 tmp{ 0 ^ xorNum[i] };
tmp = ror(tmp, 0x2);
tmp ^= 0x1B;
str[i] = static_cast<char>(tmp);
}
return string(str);
}
int getSerial(string name)
{
UINT32 sumOfName{ 0 };
for (char ch : name)
sumOfName += ch;
sumOfName = rol(sumOfName, 3);
sumOfName ^= 0x515A5;
return ((0x797E7 - sumOfName) ^ 0x87CA);
}
int main()
{
cout << "key file content: " << getKeyFileContent() << endl;
string name;
cout << "input name: " << ends;
cin >> name;
cout << getSerial(name) << endl;
}
013-Acid burn
# name/serial
name = "Gqqqq"
print("CW-%d-CRACKED" % (ord(name[0])* 0x29 * 2))
# Serial
"Hello Dude!"
014-Splish
# 校验算法
def check():
ls_name = []
for i, eax in enumerate("abcdef"):
edx = ord(eax) % 10
edx ^= i
edx += 2
if edx >= 10:
edx -= 10
ls_name.append(edx)
ls_serial = []
for i, eax in enumerate("1111111"):
ls_serial.append((ord(eax) % 10))
for i in range(6):
if ls_name[i] != ls_serial[i]:
raise Exception("error")
print("right")
# keygen
ls_name = []
for i, eax in enumerate("abcdef"):
edx = ord(eax) % 10
edx ^= i
edx += 2
if edx >= 10:
edx -= 10
ls_name.append(edx)
ls = map(lambda i: chr(i+100), ls_name)
print("".join(list(ls)))
017-Cabeca
在输入用户名时没按下一个按键就触发一下计算序列码事件
计算过程使用了switch语句,使用od可以识别,使用x32dbg会识别错误,需要手动修正
使用内存断点找到计算代码,通过堆栈找到调用的call,正确进入此函数,主要是循环使用switch语句进行加法得到序列码
018-crackme_0006 (浮点数)
算法较难,用到了浮点数算法
fninit 初始化FPU
fild st(0),dword ptr ss:[ebp+8] 浮点加载整数命令
fld st(0),st(0) 数据压栈到浮点栈寄存器st0,st0的数据压倒st1,以此类推
fmulp st(1),st(0) 浮点乘,出栈
fild st(0),dword ptr ss:[ebp+C]
fld st(0),st(0)
fmulp st(1),st(0)
faddp st(1),st(0) 浮点加出栈
fsqrt 平方根
fistp dword ptr ss:[ebp-4],st(0) 浮点数以整数的形式存放
写注册机时因类型转换的有符号无符号问题花了很多时间
查看代码
#include <iostream>
#include <Windows.h>
#include <cstdio>
#include <cmath>
using namespace std;
string str = "071362de9f8ab45c";
int main()
{
unsigned long c;
unsigned long d;
GetVolumeInformation("C:\\", nullptr, 0, &c, nullptr, nullptr, nullptr, 0);
GetVolumeInformation("D:\\", nullptr, 0, &d, nullptr, nullptr, nullptr, 0);
cout << c << " - " << (int)d << endl;
double cc = (double)((int)c);
double dd = (double)((int)d); // 注意此处,将其视为有符号数
int e = (int)sqrt((cc * cc) + (dd * dd)); // 此处也要转换为int
string name{ "qwer" };
int product{ 1 };
for (auto c : name)
{
product *= c;
}
product = product << 1 | product >> (sizeof(product)*8 - 1);
product = (product | e) & 0xFFFFFFF;
string serial{""};
do
{
auto ecx = product % 16;
serial += str[ecx];
product /= 4;
} while (product != 0);
cout << serial << endl; // cccccccccce4c3
return 0;
}
019-Acid Bytes.3
可找到用户名密码字符串
020-cosh.3
查看代码
int main()
{
string name {"qwerty"};
string code {""};
int tmp1 {1};
int tmp2 {0xA};
for (auto c : name)
{
code.insert(code.end(), static_cast<char>(c ^ tmp1 ^ tmp2));
tmp1++;
tmp2++;
}
cout << code << "<" << endl;
return 0;
}
021-DIS[IP]-Serialme
注意name与pass存储在内存中时,存储地址较近,如果name太长则会覆盖pass
查看代码
int main()
{
string name {"qwer"};
//string pass {"123456"};
for (int i = 0; i < name.size(); i++)
{
INT8 bl = name[i];
if (bl == 'z' || bl == 'Z' || bl == '9') {
bl--;
}
bl++;
INT8 bh = (i + 0x61);
printf("%c%c", bl, bh);
}
return 0;
}
022-CM_2
密码:6287-A
023-TraceMe
查看代码
#include <iostream>
#include <algorithm>
#include <Windows.h>
#include <string>
using namespace std;
int main()
{
int arr[] = { 0x0C, 0x0A, 0x13 ,0x09 ,0x0C ,0x0B ,0x0A ,0x08 };
string name{ "oouivsisfvgokrtejf" };
int sum {0};
for (int i = 3, eax = 0; i < name.size(); i++, eax++)
{
if (eax > 7) {
eax = 0;
}
sum += name[i] * arr[eax];
}
printf("%d", sum);
}
024-reverseMe
程序同一目录下创建一个名为《keyfile.dat》的文件,内容包括8个或8个以上的字符‘G’
025-CRC-32crackme(CRC32算法,复杂,不会)
将用户名前加上 DiKeN 并计算CRC32校验值,和code对比。crc算法较复杂,不会分析。
026-KeygenMe
查看代码
#include <iostream>
#include <Windows.h>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
while (true)
{
string pass = "";
string name = "";
int sum = 0;
srand(time(0));
for (int i = 0; i < 7; i++) {
char c = (rand() % (122 - 97)) + 97;
name.push_back(c);
}
for (int i = 0; i < name.size(); i++) {
int var1 = name[i];
sum += (var1 * var1);
int var2 = (var1 / 2 + 3) * var1 - var1;
sum += var2;
sum *= 2;
}
bool flag = true;
for (int i = 0; i < 4; i++) {
char c = (char)(sum >> (8*i));
if (c == 0) {
if (sum >> (8*i) == 0) {
break;
} else {
flag = false;
break;
}
}
if (c < 33 || c > 126) {
flag = false;
break;
}
pass.push_back(c);
}
if (flag) {
cout << name << endl;
cout << pass << endl;
break;
}
}
return 0;
}
030-Acid Bytes.4
upx壳,去neg
查看代码
#include <iostream>
#include <Windows.h>
#include <string>
#include <cstdlib>
using namespace std;
int main()
{
string name = "qwertyui";
int sum = 0;
for (int i = 0; i < 6; i++) {
char c = name[i];
sum += (int)c * 2;
}
sum += name.size() * 2;
printf("%d", sum);
return 0;
}
031-Cruehead.1
查看代码
name = 'dksofpdlc' # 大于 'Z' 则减 0x20
name = name.upper()
edi = 0
for c in name:
edi += ord(c)
edi ^= 0x5678
print(edi ^ 0x1234)
# 处理密码的算法:将数字字符串转化为数字,再异或0x1234
def fun(password: str):
edi = 0
for ebx in password:
ebx = ord(ebx) - 0x30
edi *= 0xA
edi += ebx
edi ^= 0x1234
return edi
032-Bengaly-Crackme2
查看代码
s1 = '12345'
num1 = 0
for ch in s1:
num1 += ord(ch) ** 2
num1 += ord(ch) // 2
num1 -= ord(ch)
print(num1)
033-***dccrackme1 (算法易,定位爆破点和算法难)
参考:https://www.bilibili.com/video/BV1Wm4y1D7aN/?p=34
name = input('input your name: ')
ans = 0
for ch in name:
num = ord(ch)
ans += (num - 0x11) * (num - 0x17)
print(ans)