jarvisoj-Evil Exe

题目描述如下:

赛题背景: 员工小A收到了一封邮件,带一个文档附件,小A随手打开了附件。随后IT部门发现小A的电脑发出了异常网络访问请求,进一步调查发现小A当时所打开的附件其实是一个伪装成word文档的恶意可执行文件。

赛题描述: 请在试着分析evil.exe和其所下载的x.jpg, 从中找出key.

评分标准: 密钥正确则可进入下一题。

主要附件为一个evil.exe程序和一个x.jpg.点击evil.exe运行后发现生成了一个evil.docx的文档(附加:要交的flag为邮箱地址!)

一开始思路以为是会有类似于与dll注入的现象,后来使用PEview发现并没有可疑的dll,随后用正常思路分析

①使用exeinfope查看该exe文件发现说有三个节区像是被upx压缩,使用upx解压缩失败

②使用ollydebug动态调试找到OEP,并脱壳

程序入口点在0043dc85处,继续调试会发现要经历eax(1190)次才能运行到0043dca3 即jmp evil.043dab0处(我最开始调试不用这么多次的!!!不知道为什么后来就是这么多次了,有试着改汇编代码让它直接跳过去,后来不行!!!这部分也是很关键的部分,f9运行到断点处时会在retn停下来,呀呀呀,只能能不停按了)

 

 

 2)运行到0043dca3处,执行跳到43dab0处,发现

 

 

 执行完pushad操作后,在相应的栈地址处设置硬件断点(图里面不小心多运行了几步>^<,不过问题不大,设置断点的操作是一样的)

 设置完断点后,直接f9件运行,程序会在执行popad访问到设置断点的地址后自动停下来,在其之后的jmp指令跳到的地方,也就是oep处

 

 

 OEP处如下:

 

 

 此时使用od的dump即可成功脱壳!

 

 

 ③使用ida打开脱壳后的文件,f5反编译进入主函数,代码片段如下:

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  void *v5; // ST10_4
  char v6; // [esp+4h] [ebp-118h]
  size_t dwSize; // [esp+114h] [ebp-8h]
  void *v8; // [esp+118h] [ebp-4h]

  if ( sub_401370(hInstance) == 6 )
    return 0;
  sub_401620();
  v8 = (void *)sub_4018F0(&dwSize);
  if ( v8 )
  {
    if ( dwSize )
    {
      v5 = malloc(dwSize);
      sub_401740(&v6, -176926348, 4884308);//Initkey
      sub_401800(&v6, v8, v5, dwSize);//decrypt
      sub_401220(v5, dwSize);//Execshellcode
    }
    free(v8);
  }
  return 0;
}

逐个点击函数,sub_4018f0()函数如下:

 

 

 可发现此函数通过使用InternetOpenUrlA()API函数从网站上下载x.jpg文件(也就是附件中所给处的文件),最后函数返回,v8为数据的首地址,dwsize为数据大小

④继续往下看,发现三个不知名函数(不晓得用途,猜测和要求的flag有关,之后实在有点不明所以,看writeup发现那个v6是key,函数名注释中给出),因此大概的流程就是根据x.jpg中的数据以及经过sub_401740函数(Initkey)给出的key来求出原本从网上下载来的数据。

⑤进入sub_401740(&v6, 0x4A8754F5745174)函数,如下:

 

 

 这里求出了key的值,通过写脚本,我们也可以得到

⑥进入sub_401800(v6, (int)v8, (int)v5, dwSize);函数,如下:

 

 

 此函数对下载文件中的内容进行了一轮异或运算。最终的结果放在了a3中,也就是主函数中的v5

⑦进入sub_401220(v5, dwSize);函数中,如下:

 

此函数对经过decrypt函数处理后的数据再进行了一次异或运算 ,因此到这里程序的运行流程就清楚了!

⑧写出脚本,如下:

a=open("D:\Desktop\做题文件\8.4\\rebuilt.3.Evil.exe\\x.jpg","rb")
b=a.read()
print(b)
a2=[]

c=0x4A8754F5745174
v6=[]
v6.append(0)
v6.append(0)
v4=[]
for i in range(8):
    v4.append(c&0xff)
    c=c>>8

for i in range(256):#求出key值
    x=i+v4[i%8]
    v6.append(x)
#print(v6)
d=open("D:\Desktop\做题文件\8.4\\dump.txt","wb")
temp=b''
for i in range(len(b)):
    v6[0]=(v6[0]+1)%256
    v6[1]=(v6[v6[0]+2]+v6[1])%256#这里要注意!IDA代码中类型从int转变为了int8类型
    v4=v6[v6[0]+2]
    v5=v6[v6[1]+2]
    v6[v6[0]+2]=v5
    v6[v6[1]+2]=v4
    x=(b[i]^v6[(v5+v4)%256+2]^i)%256
    print(hex(x),end=' ')
    temp+=bytes([x])

print(temp)
d.write(temp)#将数据写入dump.txt文件中
d.close()

运行后,dump.txt中结果如下:

 

 emmm感觉flag已经出来了哈但又不对劲,看了writeup说这是shellcode,里面的元数据0x68代表push,每个push后的数据就是我们的flag片段,因此写脚本可得出(注意数据在内存中的顺序为小端顺序!!!),这里还可以把数据在ollydebug中直接copy上去,od会将硬编码转换为看的懂的汇编代码,从中筛选处有push的,把数据结合起来一样是答案!

如下:

flag = []
i = 0
while(i<len(dump)):
    if(new_data[i]==0x68):
        flag.append(dump[i+1:i+5])
        i += 3
    i += 1

print(flag[::-1])#转换顺序
for i in flag[::-1]:
    print(str(i)[2:-1], end='')#去掉数据前的b'以及数据末尾的'

运行结果如下

 

 到这里就得到了我们的flag!!!(过程艰辛!调试过程中,电脑还崩溃了>~<)

 

posted @ 2020-08-04 23:18  jane_315  阅读(548)  评论(0编辑  收藏  举报