Jarvis OJ部分逆向
阅读原文时间:2023年07月11日阅读:2

Jarvis OJ部分逆向题解

  很久没有写博客了,前天上Jarvis OJ刷了几道逆向,保持了一下感觉。都是简单题目,写个writeup记录一下。

int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rdi
char v5; // [rsp+0h] [rbp-38h]
char v6; // [rsp+1h] [rbp-37h]
char v7; // [rsp+2h] [rbp-36h]
char v8; // [rsp+3h] [rbp-35h]
char v9; // [rsp+4h] [rbp-34h]
char v10; // [rsp+5h] [rbp-33h]
unsigned __int8 v11; // [rsp+10h] [rbp-28h]
_BYTE v12[7]; // [rsp+11h] [rbp-27h]

v5 = -85;
v6 = -35;
v7 = 51;
v8 = 84;
v9 = 53;
v10 = -17;
printf((unsigned __int64)"Input your password:");
_isoc99_scanf((unsigned __int64)"%s");
if ( strlen((const char *)&v11) == 26 ) // 这里的strlen函数被去符号表解析了
{
v3 = 0LL;
if ( (v11 ^ 0xAB) == list1 ) // 输入的第一个字母:"P",list1这里有关键数据
{
while ( (v12[v3] ^ (unsigned __int8)*(&v5 + ((signed int)v3 + 1) % 6)) == byte_6B41D1[v3] )
{
if ( ++v3 == 25 )
{
printf((unsigned __int64)"Congratulations!");
return 0;
}
}
}
}
printf((unsigned __int64)"Password Wrong!! Please try again.");
return 0;
}

  静态分析找到代码,把byte_6841D1和list1那里的关键数据提取出来,直接逆向算法。

ch=[171,221,51,84,53,239]
list1=[0x9E,0x67,0x12,0x4E,0x9D,0x98,0xAB,0,6,0x46,0x8A,0xF4,0xB4,6,0x0B,0x43,0xDC,0xD9,0xA4,0x6C,0x31,0x74,0x9C,0xD2,0xA0]
print(len(list1))
temp,temp_ch=0,''
flag=''
flag+='P'
for i in range(25):
temp=list1[i]^ch[(i+1)%6]
temp_ch=chr(temp)
print(temp_ch)
flag+=temp_ch
print(flag)

int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
char Dest; // [rsp+20h] [rbp-80h]
FILE *v5; // [rsp+88h] [rbp-18h]
FILE *File; // [rsp+90h] [rbp-10h]
char v7; // [rsp+9Fh] [rbp-1h]
const char **v8; // [rsp+B8h] [rbp+18h]

v8 = argv;
if ( argc <= 1 ) { printf("Usage: %s [FileName]\n", *argv, envp); printf("FileName是待加密的文件"); exit(1); } File = fopen(argv[1], "rb+"); if ( File ) { v5 = fopen("tmp", "wb+"); // v5是文件操作符 while ( feof(File) == 0 ) { v7 = fgetc(File); if ( v7 != -1 && v7 ) // -1表示读取到文件末尾EOF { if ( v7 > 47 && v7 <= 96 )
{
v7 += 53;
}
else if ( v7 <= 46 )
{
v7 += v7 % 11;
}
else
{
v7 = 61 * (v7 / 61);
}
fputc(v7, v5);
}
}
fclose(v5);
fclose(File);
sprintf(&Dest, "del %s", v8[1]);
system(&Dest);
sprintf(&Dest, "ren tmp %s", v8[1]);
system(&Dest);
result = 0;
}
else
{
printf("无法打开文件%s\n", v8[1]);
result = -1;
}
return result;
}

  这里提供了flag的加密文件flag.enc,从关键代码这里来看,我们只要在字母表中找准对应的映射就可以了。脚本如下:

# -*- coding: utf-8 -*
import string
with open("C://Users//wolf//Desktop//babyscrack//flag.enc",'rb+') as f:
flag_info=f.read()
print(flag_info)
def encrypto(a):
if a!='\xff' and a:
if ord(a)>47 and ord(a)<=96:
a=chr(ord(a)+53)
elif ord(a)<=46:
a=chr(ord(a)+ord(a)%11)
else:
a=chr(61*(ord(a)/61))
return a
enc='jeihjiiklwjnk{ljj{kflghhj{ilk{k{kij{ihlgkfkhkwhhjgly'
print(string.printable)
flag=""
for i in enc:
for j in string.printable:
if i==encrypto(j):
flag+=j
break
print(flag.decode('hex'))

  这道题有一个小坑点在int8那里,表明是取后8位做抑或。

signed int __cdecl check(int a1)
{
int v1; // eax
int v3; // edx

if ( a1 )
{
v1 = sub_804849C(a1);
if ( v1 )
{
if ( v1 == 29 )
{
v3 = 0;
while ( *(_BYTE *)(a1 + v3) == byte_8049AE0[(unsigned __int8)((unsigned __int8)byte_8049B15[v3] / 3u - 2)] )
{
if ( ++v3 == 29 )
return 1;
}
}
}
}
return 0;
}

s="k2j9Gh}AgfY4ds-a6QW1#k5ER_T[cvLbV7nOm3ZeX{CMt8SZo]U"
flag_info=[0x48,0x5D,0x8D,0x24,0x84,0x27,0x99,0x9F,0x54,0x18,0x1E,0x69,0x7E,0x33,
0x15,0x72,0x8D,0x33,0x24,0x63,0x21,0x54,0x0C,0x78,0x78,0x78,0x78,0x78,0x1B]
print(len(flag_info))
print(len(s))
index,temp,flag,idx=0,"","",[]
for i in flag_info:
temp=bin(i/3-2)
if len(temp)>=10:
temp=temp[-8:]
else:
temp=temp[2:]
index=int(temp,2)
idx.append(index)
for i in idx:
flag+=s[i-1]
print(flag)

  这题有个反调试,但是不影响,静态分析就能出。start函数和dummy函数地址相减的地方注意一下,逻辑写正确即可。

int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
signed int v4; // [rsp+1Ch] [rbp-14h]
int v5; // [rsp+24h] [rbp-Ch]

v5 = ((unsigned __int64)((char *)start - (char *)dummy) >> 2) ^ flag_data[0];
result = anti_debug();
if ( !(result & 1) )
{
v4 = 0;
while ( v4 < 55 )
{
flag_data[v4] -= 2;
flag_data[v4] ^= v5;
++v4;
++v5;
}
result = printf("\nFinal output is %s\n", &flag_data[1]);
}
return result;
}

flag_data=[0x41, 0x10, 0x11,0x11,0x1B, 0x0A, 0x64, 0x67, 0x6A, 0x68,
0x62, 0x68, 0x6E, 0x67, 0x68, 0x6B, 0x62, 0x3D, 0x65, 0x6A,0x6A,
0x3D, 0x68, 0x4, 0x5, 0x8, 0x3, 0x2,0x2, 0x55, 8, 0x5D, 0x61, 0x55,
0xA, 0x5F, 0x0D, 0x5D, 0x61, 0x32, 0x17, 0x1D, 0x19, 0x1F, 0x18,
0x20, 0x4, 0x2, 0x12, 0x16, 0x1E, 0x54,0x20,0x13,0x14]
print(len(flag_data))
v5=((0xcb0-0xc90)>>2)^flag_data[0]
v4,flag=0,""
while(v4<55):
flag_data[v4]-=2
flag_data[v4]^=v5
flag+=chr(flag_data[v4])
v4+=1
v5+=1
print(flag)

  这道题去了符号表,加了返混淆,好像还是C#写的,但是没关系,直接去找字符串常量,发现有一串字符串

  一看就是base64加密的,解密之后就是flag。

  这是一道python逆向的题目,直接用IDA看显示的就是字节码。在linux下用file查一下,发现应该是一个pyc,这时候用在线网站进行一步反汇编,拿到源码之后,逆向算法,exp如下所示。

lookup = [196,153,149,206,17,221,10,217,167,18,36,135,103,61,111,31,92,152,21,228,105,191,
173,41,2,245,23,144,1,246,89,178,182,119,38,85,48,226,165,241,166,214,71,90,151,3,
109,169,150,224,69,156,158,57,181,29,200,37,51,252,227,93,65,82,66,80,170,77,49,177,
81,94,202,107,25,73,148,98,129,231,212,14,84,121,174,171,64,180,233,74,140,242,75,
104,253,44,39,87,86,27,68,22,55,76,35,248,96,5,56,20,161,213,238,220,72,100,247,8,
63,249,145,243,155,222,122,32,43,186,0,102,216,126,15,42,115,138,240,147,229,204,117,
223,141,159,131,232,124,254,60,116,46,113,79,16,128,6,251,40,205,137,199,83,54,188,19,
184,201,110,255,26,91,211,132,160,168,154,185,183,244,78,33,123,28,59,12,210,218,47,
163,215,209,108,235,237,118,101,24,234,106,143,88,9,136,95,30,193,176,225,198,197,194,
239,134,162,192,11,70,58,187,50,67,236,230,13,99,190,208,207,7,53,219,203,62,114,127,
125,164,179,175,112,172,250,133,130,52,189,97,146,34,157,120,195,45,4,142,139]
pwda = [188,155,11,58,251,208,204,202,150,120,206,237,114,92,126,6,42]
pwdb = [53,222,230,35,67,248,226,216,17,209,32,2,181,200,171,60,108]

flag,temp="",0
for i in range(0,17):
temp=lookup[i+pwdb[i]]-pwda[i]&255
flag+=chr(temp)
flag=flag[::-1]
print(flag)

  这道题肯定用strip把符号表全部都去掉了。静态分析的时候,修复符号表当然是一种思路,但是还是不够,我修复了大概7000个函数,还是很难找到关键代码,而且在IDA中找不到程序运行过程中出现过的一些字符串。这种时候,直接用OD的中文搜索引擎去找一些特殊的字符串,找到“你赢了”,然后很快地就可以定位到关键代码段。

  脚本如下。

array_1=[0x1b,0x1c,0x17,0x46,0xf4,0xfd,0x20,0x30,0xb7,0xc,0x8e,0x7e,0x78,0xDE]
array_2=[0xff,0x1a,0x4e,0xe4,0x53,0xe3,0x51,0x65,0x8f,0x93,0x6B,0x64,0x57,0x28]
array_2=array_2[::-1]
flag,temp="",0
for i in range(14):
temp=array_1[i]^array_2[i]
flag+=chr(temp)
print(flag)

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章