北邮网安杯2019线上赛wp

2019-02-07  本文已影响0人  2st

Re1:RE1

State:Solved

签到题,没啥好说的,OD直接跟入提字符串即可。


flag:BUPT{R3_1s_qu17e_3!mple:)}

Re2:RE2

State:Solved

按惯例,直接拖入IDA,F5



刚开始看到这个结构有点懵逼,跟进函数分析可以得到如图结构
跟进sub_401150可以发现sub_401000是处理函数,但是被加密了


.text:00401008 dword_401008    dd 5555554Dh, 6515DE6Bh, 15E35A6Bh, 0A910DC57h, 0D0A910DEh
.text:00401008                 dd 3F522095h, 56B2BD55h, 32E45555h, 0E70AE506h, 20DE0330h
.text:00401008                 dd 0B318DD5Dh, 0DDBE18DDh, 9302A318h, 931A8910h, 931D8810h
.text:00401008                 dd 93168B10h, 93128A10h, 932EB510h, 931FB410h, 9337B710h
.text:00401008                 dd 0DD3FB610h, 1093B110h, 109361B0h, 10DD33B2h, 0BC00DDBDh
.text:00401008                 dd 17BF1093h, 93B910DDh, 932CB810h, 0DD63BB10h, 1093BA10h
.text:00401008                 dd 109327A5h, 109334A4h, 0DD25A7h, 0A11093A6h, 0A0109339h
.text:00401008                 dd 0A2109336h, 0AD109328h, 0DF9C6655h, 34696451h, 2F694229h
.text:00401008                 dd 0EB5A462Ah, 1BDD695h, 55554FEAh, 0AAA2CC55h, 0BE3497D5h
.text:00401008                 dd 29146961h, 2A0F6942h, 95EB5A46h, 0EA61BDD6h, 5555554Fh
.text:00401008                 dd 0D5AAA2CCh, 4CBE1497h, 4D296569h, 412A6C69h, 0D695EB5Ah
.text:00401008                 dd 5FEA76BDh, 0CC555555h, 97D5AAA2h, 6441DD65h, 49ACD614h
.text:00401008                 dd 10D8F029h, 0DF45DF89h, 6F9FDF4Bh, 0D1792086h, 0DF43219Ch
.text:00401008                 dd 0BDF5405h, 6F9FDF54h, 0D6492086h, 93D65795h, 209CD157h
.text:00401008                 dd 66956689h, 5A95D09Ch, 0B0A94C0h, 0DE0E94DFh, 4E9608B0h
.text:00401008                 dd 8DD60A95h, 0D09C66AAh, 94C05A95h, 0E94DF0Bh, 0C308B0DEh
.text:00401008                 dd 2 dup(90909090h)

解密过程在子函数sub_4011C0中



这里进行了一些骚操作,把代码块异或0x55,块大小327(0x401000至0x401147)
用IDAPython逆回去即可

exp1:

from idaapi import *
for i in range(0x401000,0x401147):
    PatchByte(i,Byte(i)^0x55)

重新构造函数(CreatFunction),即可得到

char __usercall sub_401026@<al>(int a1@<ebp>)
{
  const char *v1; // esi
  signed int v2; // ecx
  char v3; // al
  char v4; // dl
  char result; // al

  v1 = *(a1 + 8);
  *(a1 - 26) = 'g';
  *(a1 - 21) = 'g';
  *(a1 - 10) = 'g';
  *(a1 - 36) = 'O';
  *(a1 - 35) = 'H';
  *(a1 - 34) = 'C';
  *(a1 - 33) = 'G';
  *(a1 - 32) = '{';
  *(a1 - 31) = 'J';
  *(a1 - 30) = 'b';
  *(a1 - 29) = 'j';
  *(a1 - 28) = '_';
  *(a1 - 27) = '4';
  *(a1 - 25) = 'f';
  *(a1 - 24) = '_';
  *(a1 - 23) = 'e';
  *(a1 - 22) = 'B';
  *(a1 - 20) = '_';
  *(a1 - 19) = 'y';
  *(a1 - 18) = '6';
  *(a1 - 17) = '_';
  *(a1 - 16) = 'r';
  *(a1 - 15) = 'a';
  *(a1 - 14) = 'p';
  *(a1 - 13) = 'e';
  *(a1 - 12) = 'l';
  *(a1 - 11) = 'c';
  *(a1 - 9) = '}';
  *(a1 - 8) = '\0';
  v2 = 0;
  do
  {
    v3 = v1[v2];
    if ( v3 >= 97 && v3 <= 122 )
    {
      v4 = (v3 - 84) % 26 + 97;
LABEL_11:
      v1[v2] = v4;
      goto LABEL_12;
    }
    if ( v3 >= 65 && v3 <= 90 )
    {
      v4 = (v3 - 52) % 26 + 65;
      goto LABEL_11;
    }
    if ( v3 >= 48 && v3 <= 57 )
    {
      v4 = (v3 - 35) % 10 + 48;
      goto LABEL_11;
    }
LABEL_12:
    ++v2;
  }
  while ( v2 < 28 );
  if ( !strcmp((a1 - 36), v1) )
    result = nullsub_2();
  else
    result = 1;
  return result;
}

flag :OHCG{Jbj_4gf_eBg_y6_rapelcg}
再用脚本跑一下

exp2:

Plain_Text = 'OHCG{Jbj_4gf_eBg_y6_rapelcg}'

def fun(Plain_Text,shift):
    Cipher_Text = ''
    for i in Plain_Text:
        if ord(i) in range(ord('A'),ord('Z')+1):
          Cipher_Text += chr((ord(i)-ord('A')+shift)%26+ord('A'))
        elif ord(i) in range(ord('a'),ord('z')+1):
          Cipher_Text += chr((ord(i)-ord('a')+shift)%26+ord('a'))
        elif ord(i) in range(ord('0'),ord('9')+1):
          Cipher_Text += chr((ord(i)-ord('0')+shift)%10+ord('0'))
        else:
          Cipher_Text += i
    print Cipher_Text
fun(Plain_Text,-13)

得到flag为BUPT{Wow_1ts_rOt_l3_encrypt}

Re3:RE3

State:Unsolved

这里复制的官方解(实在没时间去研究了,距高考80+天,理综还在270苟延残喘,Orz

程序加了壳,壳是变形的upx壳,脱壳找到oep,dump内存。oep位置如下图:



分析dump内存,查看main函数:




程序获取了自身一个名为BIN的资源,将其带入了0x401110函数。

程序对获取到的资源pSource进行了Size次异或0x77,即解密,对解密后的资源进行一系列和PE结构相关的操作,即内存释放DLL,其中涉及判断是否该资源为DLL,将资源以内存布局加载,修改IAT表以及重定位RELOC表,最后从DllMain函数启动。其中有两处反调试,如果调试,需要留意。

获取解密后的DLL,IDA进行分析:



分析线程函数0x10001000



11个未知数,每个未知数4字节,11个方程求解,脚本如下:
from z3 import *
  import struct
  cmpValue = [3350593028, 3187659634, 1962716233, 1695120199, 2164708281, 281870293, 4234765510, 1710951488, 3280612146, 907270479, 3620629970]
  randNum = [130, 35, 99, 184, 1, 60, 50, 24, 27, 209, 161, 56, 5, 192, 46, 177, 128, 45, 141, 30, 201, 80, 161, 85, 88, 206, 148, 55, 139, 154, 177, 239, 173, 25, 37, 25, 153, 220, 33, 142, 155, 195, 64, 184, 231, 31, 55, 64, 251, 95, 28, 129, 7, 93, 188, 181, 212, 123, 161, 124, 160, 156, 76, 232, 239, 156, 138, 128, 201, 165, 210, 92, 37, 189, 68, 189, 17, 18, 151, 31, 171, 205, 233, 140, 80, 70, 214, 16, 250, 162, 89, 127, 230, 123, 76, 80, 244, 153, 94, 197, 36, 192, 95, 99, 75, 227, 112, 1, 93, 118, 69, 198, 29, 221, 148, 15, 166, 98, 44, 181, 56]
  ​
  s = Solver()
  a = [BitVec("a%d"%i, 32) for i in range(11)]
  ​
  for j in range(11):
      calValue = 0
      for i in range(11):
          calValue += a[i]*randNum[11*j+i]
          calValue &= 0xffffffff
          s.add(calValue == cmpValue[j])
  ​
  while(s.check() == sat):
      m = s.model()
      for i in a:
          print m[i],
      print ""
      exp = []
      for val in a:
          exp.append(val != m[val])
      s.add(Or(exp))
  ​
  flagint = "1414550850 1819235195 1735289206 1848656735 1634890805 1937010225 1985169759 1601794661 1702129201 1949656434 2103930417"
  tmp = flagint.split(" ")
  flag = ""
  ​
  for i in tmp:
      val = (int(i))
      # print val
      tmp = struct.pack("<I",val)
      flag += tmp
  print flag

可求出两组解,其中一组解均为可见字符,另外一组舍弃。

得到flag为BUPT{Solving_C0n5tra1nts_ISvery_1ntere5t1ng}

Web1:Web1

State:Unsolved

待补坑

Web2:Web2

State:Unsolved

待补坑

Web3:Web3

State:Unsolved

待补坑

小结:这次线上题比去年略难,re2看了好一会才反应过来(毕竟半年没做逆向题),按这成绩也能苟进线下,因为高三了得收收心就没报名。总的来说题目质量很高,北邮师傅们幸苦了,今年9月见(ง •_•)ง

上一篇下一篇

猜你喜欢

热点阅读