其他
记一次逆向FreeRes0.94注册过程及注册机
1、用PEiD检测,发现加了壳:ASPack 2.001 -> Alexey Solodovnikov,用esp定律脱了并修复IAT。 继续用PEiD检测,发现是用”Borland Delphi”写的。
2、根据Delphi的特点,定位到注册界面的”确定”按钮响应函数在位置:0x004C2D68
用IDA分析这个注册函数
发现除了把注册名字和注册码写入注册表之后就没干其他事情了,然后继续找检测注册码的关键点。刚好用到“建立可编辑资源“这个功能的时候出现了如下的提示框:
通过这个现象说明在这个功能上做了注册的检测,根据上面找”确定”按钮同样的方法找到”建立可编辑资源”这个菜单的响应函数在:0x004CD2D0
继续用IDA分析这个函数,定位到sub_4BBC00为检测注册码的函数
3、分析地址0x004CD332处调用的 CheckCode_4BBC00 这个检测函数
4、注册机,注册机用一个类简单的封装了一下,代码如下,完整源码在附件
class KeyGen
{
public:
KeyGen();
~KeyGen();
public:
int ReverseRegCode(const std::string &strUser, const std::string &strMachine,
DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, std::string &RegCode);
protected:
int Format_Name(const std::string &strUser, const std::string &strMachineCode, std::string &str_user_mc);
int Calc_Name(const std::string &str_user_mc, DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_out, DWORD dw_8C34);
/*
int Format_Calc_Name(const std::string &strUser, const std::string &strMachineCode,
DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_out, DWORD dw_8C34);
int Calc_Name_Again(unsigned char *pc_in, unsigned char *&pc_out);
//IDA里面的Calc_RegCode,反算注册码部分算了两轮,分别是下面两个函数
int CalcRegCodeFirstRound(const std::string &strRegCode, unsigned char*&pc_out);
int CalcRegCodeSecondRound(DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_in, DWORD dw_8C34, unsigned char *&pc_out);
int sub_4BB780(unsigned char c);
int sub_4BB794(unsigned char c);
int Calc(const std::string &strUser, const std::string &strMachineCode);
*/
bool DfsRegCode(DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, int index);
int ReverseOneChar(unsigned char fc, unsigned char sc, unsigned char &c_out);
private:
unsigned char *m_VisiableChar;
unsigned char *m_pName;
unsigned char *m_RegCode;
unsigned int m_vc_len;
unsigned int m_name_len;
};
int KeyGen::ReverseRegCode(const std::string &strUser, const std::string &strMachineCode,
DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, std::string &RegCode)
{
std::string str_user_mc = "";
Format_Name(strUser, strMachineCode, str_user_mc);
unsigned char *pName = NULL;
Calc_Name(str_user_mc, dw_3D6, dw_3183, pName, dw_8C34);
unsigned char *pRegCode = new unsigned char[0x29];
memset(pRegCode, 0, 0x29);
unsigned char visiable_char[] = {
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'1','2','3','4','5','6','7','8','9','0','~','`','!','@','#','$','%','^','&','*','(',')','-','_','=','+',
'[','{',']','}',';',':','\'','\"','\\','|',',','<','.','>','/','?',' ','\0' };
m_VisiableChar = visiable_char;
m_pName = pName;
m_RegCode = pRegCode;
bool b_find = false;
m_name_len = strlen(str_user_mc.c_str());
m_vc_len = strlen((char*)visiable_char);
b_find = DfsRegCode(dw_3D6, dw_3183, dw_8C34, 0);
if (b_find)
{
RegCode = (char*)pRegCode;
}
delete[] pName;
pName = NULL;
delete[] pRegCode;
pRegCode = NULL;
return 0;
}
int KeyGen::Format_Name(const std::string &strUser, const std::string &strMachineCode, std::string &str_user_mc)
{
str_user_mc = strUser.c_str();
str_user_mc += strMachineCode.c_str();
size_t len = strlen(str_user_mc.c_str());
if (len <= 0x12)
{
char cb = str_user_mc[len - 1];
char var_D = cb;
int var_14 = 0;
if (cb <= 0x7F)
{
var_14 = 1;
}
else
{
var_14 = -1;
}
int var_15 = 0x12 - len;
for (size_t i = 0; i < var_15; i++)
{
cb += var_14;
str_user_mc.insert(str_user_mc.begin(), 1, cb);
}
str_user_mc.insert(str_user_mc.begin(), 1, var_D);
}
else
{
unsigned char cb = str_user_mc[0x12];
if (len >= 0x14)
{
unsigned char cd = '\0';
int var_15 = len - 0x14 + 1;
int pos = 0x14;
for (size_t i = 0; i < var_15; i++)
{
cd = str_user_mc[pos - 1];
if (cb > cd)
{
cb -= cd;
}
else
{
cd -= cb;
cb = cd;
}
pos++;
}
}
str_user_mc = str_user_mc.substr(0, 0x12);
if (cb==0)
{
cb = 0xFF;
}
str_user_mc.insert(str_user_mc.begin(), 1, cb);
}
if (len > 0xFF)
{
len = 0xFF;
}
char var_28 = len;
str_user_mc.insert(str_user_mc.begin()+1, 1, var_28);
return 0;
}
int KeyGen::Calc_Name(const std::string &str_user_mc, DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_out, DWORD dw_8C34)
{
pc_out = NULL;
int len = strlen(str_user_mc.c_str());
if (len <= 0)
{
return -2;
}
pc_out = new unsigned char[0x29];
memset(pc_out, 0, 0x29);
int var_9 = len;
unsigned char c = 0;
DWORD var_3D6 = dw_3D6;
DWORD var_tmp = dw_3D6;
for (size_t i = 0; i < len; i++)
{
c = str_user_mc[i];
var_tmp = var_3D6;
var_tmp >>= 0x8;
c ^= (var_tmp & 0xFF);
pc_out[i] = c;
var_3D6 += pc_out[i];
var_3D6 *= dw_3183;
var_3D6 += dw_8C34;
}
pc_out[len] = '\0';
return 0;
}
bool KeyGen::DfsRegCode(DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, int index)
{
if (index == m_name_len)
{
return true;
}
bool b_find = false;
unsigned char c_out = 0;
unsigned int var_3D6 = dw_3D6;
for (size_t i = 0; i < m_vc_len; i++)
{
for (size_t j = 0; j < m_vc_len; j++)
{
ReverseOneChar(m_VisiableChar[i], m_VisiableChar[j], c_out);
unsigned int var_tmp = 0;
unsigned char c_tmp = c_out;
var_tmp = var_3D6;
var_tmp >>= 0x8;
c_out ^= var_tmp;
if (c_out == m_pName[index])
{
m_RegCode[2 * index] = m_VisiableChar[i];
m_RegCode[2 * index + 1] = m_VisiableChar[j];
var_3D6 += c_tmp;
var_3D6 *= dw_3183;
var_3D6 += dw_8C34;
b_find = DfsRegCode(var_3D6, dw_3183, dw_8C34, index+1);
if (b_find)
{
break;
}
else
{
var_3D6 = dw_3D6;
}
}
}
if (b_find)
{
break;
}
}
return b_find;
}
int KeyGen::ReverseOneChar(unsigned char fc, unsigned char sc, unsigned char &c_out)
{
unsigned char cb = '\0';
unsigned char ca = '\0';
unsigned char cd = '\0';
unsigned char cc = '\0';
unsigned char var_9 = 0;
unsigned char var_A = 0;
cb = fc;
ca = sc;
cd = ca;
cd &= 0x4F;
var_9 = cd;
cd = ca;
cd &= 0x30;
cd >>= 0x4;
var_A = cd;
unsigned char temp = ca & 0x40;
if (temp == 0)
{
cb = 0;
}
else
{
if (var_9 < 0x43)
{
ca = 0x43;
ca -= var_9;
var_9 = ca;
cc = var_9;
cb <<= cc;
cb |= var_A;
}
else if (var_9 > 0x43)
{
var_9 -= 0x43;
cc = var_9;
ca = cb;
ca >>= cc;
cb = ca;
}
else
{ }
}
c_out = cb;
return 0;
}
//输入注册名字和机器码
int main(int argc, char** argv)
{
if (argc < 3)
{
return 0;
}
std::string RegCode = "";
//第一个参数为注册名字,第二个参数为机器码
KeyGen kg;
kg.ReverseRegCode(argv[1], argv[2], 0x3D6, 0x3183, 0x8C34, RegCode);
printf("regcode=%s\n", RegCode.c_str());
return 0;
}
本文由看雪论坛 MTRush 原创
转载请注明来自看雪社区
往期热门阅读:
点击阅读原文/read,
更多干货等着你~
扫描二维码关注我们,更多干货等你来拿!