XCTF题目easy-apk答题
将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;
byte tmp = 0;
int k;
for(k = 0; k <= 2; ++k)
{
if(i + k <= arg9.length - 1)
{
enBytes = (byte)((arg9 & 0xFF) >>> k * 2 + 2 | tmp);
tmp = (byte)(((arg9 & 0xFF) << (2 - k) * 2 + 2 & 0xFF) >>> 2);
}
else
{
enBytes = tmp;
tmp = 0x40;
}
}
enBytes = tmp;
int v2_1;
for(v2_1 = 0; v2_1 <= 3; ++v2_1)
{
if(enBytes <= 0x3F)
{
res.append(Base64New.Base64ByteToStr]);
}
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)); //取对应字符
}
}
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 charoldc[] = {'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;
newstr ='\0';
for(int i = 0 ; i < clen ; i++)
{
int nnum = getcindex(oldstr);
if(nnum!= -1)
newstr = newc;
else
newstr = oldstr;
}
ui->lineEdit_2->setText(QString(newstr));
}
int MainWindow::getcindex(char cc)
{
for(int i = 0 ; i < 64 ; i++)
{
if(cc == oldc)
return i;
}
return -1;
}
```
对apk中的字符串转换之后
再找个标准base64解密
但是提交的时候提示错误,不知道原因?
搜索了下知道了,是要加flag{} 可惜我是个web狗 是将正常的Base64加密函数替换了代码APK中Base64Encode()函数,然后再打包是吗? pwn狗报道 向技术大佬致敬{:1_893:} 1372_7 发表于 2020-8-4 16:22
是将正常的Base64加密函数替换了代码APK中Base64Encode()函数,然后再打包是吗?
不是,apk提供一个新64字符表的base64加密方法和加密后的字符串,要你解密出原字符串。 这边可能还是一层加密
页:
[1]