好友
阅读权限10
听众
最后登录1970-1-1
|
CM是什么?Crackme是什么?这是什么东西?楼主发的什么?
他们都是一些公开给别人尝试破解的小程序,制作 Crackme 的人可能是程序员,想测试一下自己的软件保护技术,也可能是一位 Cracker,想挑战一下其它 Cracker 的破解实力,也可能是一些正在学习破解的人,自己编一些小程序给自己破解,KeyGenMe是要求别人做出它的 keygen (序号产生器), ReverseMe 要求别人把它的算法做出逆向分析, UnpackMe 是要求别人把它成功脱壳,本版块禁止回复非技术无关水贴。
将apk拖入JEB查,查看入口:
<activity android:name="com.testjava.jack.pingan1.MainActivity">
进入MainActivity,查看发现关键位置代码
if(new Base64New().Base64Encode(strIn.getBytes()).equals("5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs="))
{
Toast.makeText(MainActivity.this, "验证通过!", 1).show();
return;
}
Toast.makeText(MainActivity.this, "验证失败!", 1).show();
是通过Base64New类的Base64Encode()函数,对用户输入的字符串进行处理后与"5rFf7E2K6rqN7Hpiyush7E6S5fJg6rsi5NBf6NGT5rs="进行比较。
那么就进去Base64New类查看Base64Encode()函数是如何对字符串进行处理的,处理函数如下。
public String Base64Encode(byte[] arg9)
{
StringBuilder res = new StringBuilder();
int i;
for(i = 0; i <= arg9.length - 1; i += 3)
{
byte[] enBytes = new byte[4];
byte tmp = 0;
int k;
for(k = 0; k <= 2; ++k)
{
if(i + k <= arg9.length - 1)
{
enBytes[k] = (byte)((arg9[i + k] & 0xFF) >>> k * 2 + 2 | tmp);
tmp = (byte)(((arg9[i + k] & 0xFF) << (2 - k) * 2 + 2 & 0xFF) >>> 2);
}
else
{
enBytes[k] = tmp;
tmp = 0x40;
}
}
enBytes[3] = tmp;
int v2_1;
for(v2_1 = 0; v2_1 <= 3; ++v2_1)
{
if(enBytes[v2_1] <= 0x3F)
{
res.append(Base64New.Base64ByteToStr[enBytes[v2_1]]);
}
else
{
res.append('=');
}
}
}
return res.toString();
}
处理有点复杂,如果不是实在没办法我是不愿意慢慢分析如何处理的。鉴于对base64不太了解,先去找找资料。
理解理念后,自己尝试写一个base64加密,由于对最后不足3个字符加‘=’的处理形式还不理解,就先写个函数处理前面的。
const char *basedd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
QString MainWindow::getBase(char *ch)
{
int chleng = strlen(ch); //原字符串长度
int fnum = chleng/3; //可进行几个完整3转4
QString retstr; //生成字符串
for(int i = 0 ; i < fnum ; i++) //每次循环进行一次3转4
{
int tmp = *((int*)(ch+i*3)); //取前四字节放入tmp中
tmp = getreorder(tmp); //校正字节顺序
for(int j = 0 ; j < 4 ;j ++) //循环生成四个字符
{
int ch1 = (tmp>>(26-6*j))&0x3f; //将要取的6位移动到最后,其他位置0
retstr.append(QChar(basedd[ch1])); //取对应字符
}
}
return retstr;
}
int MainWindow::getreorder(int value)
{
int byte_1=(value&0xff000000)>>24;
int byte_2=(value&0x00ff0000)>>16;
int byte_3=(value&0x0000ff00)>>8;
int byte_4=value&0x000000ff;
int result=(byte_4<<24)+(byte_3<<16)+(byte_2<<8)+byte_1;
return result;
}
方法是先取字符串下标0、1、2、3的四个字节当成int类型,并将4个字节逆序(大小端对齐的问题),然后根据规律循环取6Bit生成新的字符,取够4个6位刚好是前三个字节的内容。
再取3、4、5、6下标的字节,用同样方法循环处理。这里仅处理3个一组的字符,多余的我没有处理,仅为了测试。
写完代码后再看Base64New类,发现应该是把64个字符对应的字符顺序换了。
找个解码base64的代码,将64位字符替换掉就可以。
这里我直接将apk中NEWbase64加密后的字符转换成正常base64加密后的,代码如下
const char oldc[] = {'v', 'w', 'x', 'r', 's', 't', 'u', 'o', 'p', 'q', '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'y', 'z', '0', '1', '2', 'P', 'Q', 'R', 'S', 'T', 'K', 'L', 'M', 'N', 'O', 'Z', 'a', 'b', 'c', 'd', 'U', 'V', 'W', 'X', 'Y', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', '8', '9', '+', '/'};
const char *newc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void MainWindow::on_pushButton_clicked()
{
char* oldstr = ui->lineEdit->text().toLatin1().data();
int clen = strlen(oldstr);
char newstr[clen+1];
newstr[clen+1] ='\0';
for(int i = 0 ; i < clen ; i++)
{
int nnum = getcindex(oldstr[i]);
if(nnum!= -1)
newstr[i] = newc[nnum];
else
newstr[i] = oldstr[i];
}
ui->lineEdit_2->setText(QString(newstr));
}
int MainWindow::getcindex(char cc)
{
for(int i = 0 ; i < 64 ; i++)
{
if(cc == oldc[i])
return i;
}
return -1;
}
对apk中的字符串转换之后
再找个标准base64解密
但是提交的时候提示错误,不知道原因?
|
|