diakla

导航

练习16~

normal16

password1


因为前面有个提取数字,所以可以确定这个六位密码都是数字,SHA1之后比较,暴力即可
对照:https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id

import hashlib
a=[]
for i in range(32,128):
    a.append(chr(i))
for i0 in a:
    for i1 in a:
        for i2 in a:
            for i3 in a:
                for i4 in a:
                    for i5 in a:
                        s=i0+i1+i2+i3+i4+i5+"123321@DBApp"
                        if hashlib.md5(s.encode("utf8")).hexdigest().upper()=="27019e688a4e62a649fd99cadaafdb4e":
                            print(i0+i1+i2+i3+i4+i5)
                            break
#123321

password2
同上,是md5,但是因为没有是数字的限制,暴力的话复杂度就太高了
所以先不管,看下面的比较函数

发现是首先查找名为“AAA”的资源并取出数据,然后和输入异或,之后生成了个rtf文件
大概就是答案=AAA里的前六个数据^rtf文件数据格式的前六个字符({\rtf1)
使用ResourceHacker软件查看资源,得到前六个数据为0x5,0x7D,0x41,0x15,0x26,0x1

b=[0x05,0x7D,0x41,0x15,0x26,0x01]
ss="{\\rtf1"
pw=""
for i in range(6):
    pw+=chr(b[i]^ord(ss[i]))
print(pw)
#~!3a@0

输出Error之后会生成一个rtf文件,里面是flag

normal17


前面有::的变量是全局变量
看起来是个顺序,但是CreateThread,会创建新线程
大概就是可以用 WaitForSingleObject 等待互斥体的使用权(ownership)空闲出来,并获取使用权,然后再访问和其他线程共享的资源,访问完后,用 ReleaseMutex 释放使用权,给其他线程使用的机会
然后dword_418008初始29,判断是-1,显然这两个函数交替进行了多次
第一个是减下标然后这样操作一下

第二个只有减下标,也就是偶数位不变,奇数位操作一下
然后最后很朴素的比较了一下

不知道为啥off_418004点进去没有值,是从字符串窗口一路X找到的

s1="TOiZiZtOrYaToUwPnToBsOaOapsyS"
s2="QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm"
f=""
for i in range(len(s1)):
    if i%2==0:
        f+=s1[i]
    else:
        if (ord(s1[i])>=97) and (ord(s1[i])<=122):
            f+=chr(s2.find(s1[i])+38)
        else:
            f+=chr(s2.find(s1[i])+96)
print(f)
#flag{ThisisthreadofwindowshahaIsES}

normal18

要求welcomebeijing对应的密码

两个while的结束条件是isalnum判断是否全是字母数字
loc_9311A0无法反编译,盲猜是给成功和失败的两种字符串赋值


sub_931830里的操作有点类似RC4加密,变化后的v17为dbappsec
然后动态调试找arr,先把两个if的jz改成jnz,然后进行程序的跟进,把每次循环使用到的arr记录下来
脚本

arr=[0x2A,0xD7,0x92,0xE9,0x53,0xE2,0xC4,0xCD]
str="dbappsec"
ans=""
for i in range(len(arr)):
    arr[i]=ord(str[i])^arr[i]
    ans+="%X"%arr[i]
print(ans)
# 4EB5F3992391A1AE

normal19

一开始因为花指令F5不出来,确定无效指令的位置

arr = [[0x4009A9,0x4009C7],[0x4009E0,0x4009FE],[0x400ACA,0x400AE8],[0x400B1A,0x400B38],[0x400B65,0x400B92],[0x400BEF,0x400C00]]
for i in range(len(arr)):
    for j in range(arr[i][0],arr[i][1]):
        ida_bytes.patch_byte(j,0x90)#IDA75里这个函数和其他版本的写法不一样

然后动态调试,发现有很多goto exit的地方,nop掉

arr = [[0x400972,0x400978], [0x400987,0x40098D],[0x400A2F,0x400A35],[0x400A77,0x400A7D],[0x400AAB,0x400AB1],[0x400BBC,0x400BC2]]
for i in range(len(arr)):
    for j in range(arr[i][0],arr[i][1]):
        ida_bytes.patch_byte(j,0x90)

然后在这里下断点

输入0123456789abcdefghi根据输出判断是怎么打乱的
脚本

s1="0123456789abcdefghi"
s2="8f6c90e1dg237abh5i4"
s="S@yRtfTl0+ag-L_3M}{"
ans=""
for i in range(len(s)):
    ans+=s[s2.find(s1[i])]
print(ans)
# flag{My-StL_R0T@+3}

normal20


顺序累加,减回去就行

s=[0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x7B, 0x7C, 0x7D, 0x7E]
a=[0x72, 0xE9, 0x4D, 0xAC, 0xC1, 0xD0, 0x24, 0x6B, 0xB2, 0xF5, 0xFD, 0x45, 0x49, 0x94, 0xDC, 0x10, 0x10, 0x6B, 0xA3, 0xFB, 0x5C, 0x13, 0x17, 0xE4, 0x67, 0xFE, 0x72, 0xA1, 0xC7, 0x04, 0x2B, 0xC2, 0x9D, 0x3F, 0xA7, 0x6C, 0xE7, 0xD0, 0x90, 0x71, 0x36, 0xB3, 0xAB, 0x67, 0xBF, 0x60, 0x30, 0x3E, 0x78, 0xCD, 0x6D, 0x35, 0xC8, 0x55, 0xFF, 0xC0, 0x95, 0x62, 0xE6, 0xBB, 0x57, 0x34, 0x29, 0x0E,3]
f=''
n=len(a)
m=len(s)
for i in range(0,32):
    nw=a[i]
    for j in range(0,i):
        # print(j,i-j)
        nw=((nw-(ord(f[j])^s[i-j]))%128+128)%128
    nw^=s[0]
    # print(nw)
    f+=chr(nw)
l1=a[n-1]^s[m-1]
l2=(a[n-2]-(l1^s[m-2]))^s[m-1]
f+=chr(l2)
f+=chr(l1)
print(f)
#SYC{4+mile+b3gin+with+sing1e+step}

normal21


先动态找rc4异或的8个值
断在这里,根据v9v10的值从v5[]里面找对应的值

然后暴力sub_401950的解

#include<iostream>
#include<cstdio>
using namespace std;
int v1[10];
int ck()
{
  int dword_40F020=0x8A;
  int dword_40F024=0x1A1;
  int dword_40F028=0x12A;   
  int dword_40F02C=0x269;   
  int dword_40F030=0x209;   
  int dword_40F034=0x68;    
  int dword_40F038=0x39F; 
  int dword_40F03C=0x2C8;
  int i=0;
  do
  {
    switch ( v1[i] )
    {
      case 0:
        dword_40F028 &= dword_40F038;
        dword_40F02C *= dword_40F028;
        break;
      case 1:
        if ( !dword_40F02C )
          return 0;
        dword_40F028 /= dword_40F02C;
        dword_40F024 += dword_40F034;
        break;
      case 2:
        dword_40F030 ^= dword_40F034;
        dword_40F03C += dword_40F020;
        break;
      case 3:
        dword_40F03C -= dword_40F030;
        dword_40F030 &= dword_40F024;
        break;
      case 4:
        dword_40F034 *= dword_40F020;
        dword_40F02C -= dword_40F038;
        break;
      case 5:
        dword_40F020 ^= dword_40F02C;
        dword_40F038 -= dword_40F03C;
        break;
      case 6:
        if ( !dword_40F03C )
          return 0;
        dword_40F034 |= dword_40F024 / dword_40F03C;
        dword_40F024 /= dword_40F03C;
        break;
      case 7:
        dword_40F038 += dword_40F028;
        dword_40F034 |= dword_40F024;
        break;
      case 8:
        dword_40F020 *= dword_40F02C;
        dword_40F030 -= dword_40F03C;
        break;
      case 9:
        dword_40F028 += dword_40F034;
        dword_40F02C ^= dword_40F030;
        break;
      default:
        return 0;
    }
    ++i;
  }
  while ( i < 8 );
  int result = (dword_40F038 == 231)
         + (dword_40F034 == 14456)
         + (dword_40F030 == 14961)
         + (dword_40F02C == -13264)
         + (dword_40F028 == 16)
         + (dword_40F024 == 104)
         + (dword_40F020 == -951) == 7;
  if ( dword_40F03C != -239 )
    return 0;
  return result;
}
void dfs(int w)
{
    if(w==8)
    {
        if(ck())
        {
            for(int i=0;i<8;i++)
                printf("%d,",v1[i]);
            // exit(0);
        }
        return;
    }
    for(int i=0;i<=9;i++)
    {
        v1[w]=i;
        dfs(w+1);
        v1[w]=-1;
    }
}
int main()
{
    dfs(0);
    return 0;
}
//6,1,4,9,5,0,7,2,

然后写解密脚本

a=[0x7C,0xAB,0x2D,0x91,0x2F,0x98,0xED,0xA9]
b=[6,1,4,9,5,0,7,2]
for i in range(len(a)):
    print(hex(a[i]^b[i])[2:],end='')

normal22

查壳,然后用upxshell脱壳
然后就是压一下串和已知串比较



s=[0x00000050, 0x000000C6, 0x000000F1, 0x000000E4, 0x000000E3, 0x000000E2, 0x0000009A, 0x000000A1,167,222,218,70,171,46,255,219]
f=''
for i in range(16):
    s[i]-=1
    a=s[i]>>4
    b=s[i]&15
    if a<=9:
        a+=48
    else:
        a+=87
    if b<=9:
        b+=48
    else:
        b+=87
    f+=chr(a)+chr(b)
print(f)
#4fc5f0e3e2e199a0a6ddd945aa2dfeda

normal24


就是把输入操作了一下进行xxtea加密,动态得到传入参数分别是输入字符串,输入字符串的前四个字节,00000..,加密后数组的大小
然后用z3逆出来后面的部分对加密后字符串的操作

from z3 import *
a=[0xCE,0xBC,0x40,0x6B,0x7C,0x3A,0x95,0xC0,0xEF,0x9B,0x20,0x20,0x91,0xF7,0x02,0x35,0x23,0x18,0x02,0xC8,0xE7,0x56,0x56,0xFA]
s=Solver()
f=[BitVec('%d'%i ,8) for i in range(24)]
for i in range(1,24):
    if i//3>0:
        nw=f[i]
        for j in range((int)(i/3)):
            nw^=f[j]
            f[i]=nw
for i in range(24):
    s.add(f[i]==a[i])
if s.check()==sat:
    result=s.model()
    print(result)
else:
    print('unsat')

然后找出换位前的数组

a=[206,188,64,165,178,244,231,178,157,169,18,18,200,174,91,16,6,61,29,215,248,220,220,112]
b=[2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]
f=[0]*24
for i in range(24):
    f[b[i]]=a[i]
print(f)
import struct

_DELTA = 0x9E3779B9


def _long2str(v, w):
    n = (len(v) - 1) << 2
    if w:
        m = v[-1]
        if (m < n - 3) or (m > n): 
            return ''
        n = m
    s = struct.pack('<%iL' % len(v), *v)
    return s[0:n] if w else s


def _str2long(s, w):
    n = len(s)
    m = (4 - (n & 3) & 3) + n
    s = s.ljust(m, "\0")
    v = list(struct.unpack('<%iL' % (m >> 2), s))
    if w: 
        v.append(n)
    return v



def decrypt(str, key):
    if str == '': return str
    v = _str2long(str, False)
    k = _str2long(key.ljust(16, "\0"), False)
    n = len(v) - 1
    z = v[n]
    y = v[0]
    q = 6 + 52 // (n + 1)
    sum = (q * _DELTA) & 0xffffffff
    while (sum != 0):
        e = sum >> 2 & 3
        for p in xrange(n, 0, -1):
            z = v[p - 1]
            v[p] = (v[p] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
            y = v[p]
        z = v[n]
        v[0] = (v[0] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[0 & 3 ^ e] ^ z))) & 0xffffffff
        y = v[0]
        sum = (sum - _DELTA) & 0xffffffff
    return _long2str(v, True)


if __name__ == "__main__":
    key = "flag"
    data1 = [188, 165, 206, 64, 244, 178, 178, 231, 169, 18, 157, 18, 174, 16, 200, 91, 61, 215, 6, 29, 220, 112, 248, 220]
    s = "".join(map(chr, data1))
    s = decrypt(s, key)
    print(repr(s))
#flag{CXX_and_++tea}

normal25

字符串窗口没用,S+F7找段

跟进去,找到读入


然后根据fg盲猜异或值是'flag',写脚本解密就行

a=[64,53,32,86,93,24,34,69,23,47,36,110,98,60,39,84,72,108,36,110,114,60,50,69,91]
b=[ ord('f') ^ 64,ord('l') ^ 53,ord('a')^32,ord('g')^86]
f=""
for i in range(len(a)):
    f+=chr(a[i]^b[i % 4])
print(f)
#flag{Act1ve_Defen5e_Test}

normal26


先用输入0123456789abcdefghijklmnopqrstu动态找出打乱flag的对应关系
然后暴力解出这一部分

得到:private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
根据https://www.cnblogs.com/CodeMIRACLE/p/5343660.html,还原出v2为'?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z'。
脚本:

s='1234567890-=!@#$%^&*()_'
s1='(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&'
s2='55565653255552225565565555243466334653663544426565555525555222'
ot=""
for i in range(62):
    for j in range(1,127):
        a=j%23
        b=j//23
        if s[a]==s1[i]:
            if s[b]==s2[i]:
                ot+=chr(j)
print(ot)
#private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
a='0123456789abcdefghijklmnopqrstu'
c=[0x66,0x67,0x37,0x68,0x69,0x38,0x33,0x6A,0x6B,0x39,0x6C,0x6D,0x61,0x34,0x31,0x6E,0x6F,0x62,0x70,0x71,0x63,0x35,0x72,0x73,0x64,0x74,0x75,0x65,0x36,0x32,0x30,0x0]
b=''
for i in c:
    b+=chr(i)
str4='?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z'
f=""
for i in range(len(a)):
    f+=str4[b.find(a[i])]
print(f)
#Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP

normal27

逆成py是

# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: E:/Code/python/Geek-python/python1.py
# Compiled at: 2019-10-22 16:59:55
import struct, time

def b(a):
    return a & 18446744073709551615


def c(str):
    return struct.unpack('<Q', str)[0]#打包


def d(a):
    for i in range(64):
        a = a * 2
        if a > 18446744073709551615:
            a = b(a)
            a = b(a ^ 12682219522899977907)

    return a


if __name__ == '__main__':
    cmp_data = [
     7966260180038414229, 16286944838295011030, 8598951912044448753, 7047634009948092561, 7308282357635670895]
    input = raw_input('plz input your flag:')
    if len(input) % 8 != 0:
        for i in range(8 - len(input) % 8):
            input += '\x00'

    arr = []
    for i in range(len(input) / 8):
        value = d(c(input[i * 8:i * 8 + 8]))
        arr.append(value)

    for i in range(5):
        if arr[i] != cmp_data[i]:
            print 'fail'
            time.sleep(5)
            exit()

    print 'success'
    time.sleep(5)
    exit()
# okay decompiling normal27.pyc

因为异或的是奇数,前置操作又是左移,末尾为0,所以根据奇偶性可以判断有没有进if,然后反着来就行

import struct
a=[7966260180038414229, 16286944838295011030, 8598951912044448753, 7047634009948092561, 7308282357635670895]
f=''
for x in a:
    for i in range(64):
        if x%2==0:
            x>>=1
        else:
            x=x^12682219522899977907
            x=x+(1<<64)
            x>>=1
    f+=str((struct.pack('>Q',x)[::-1].strip()),encoding='utf-8')
print(f)
#Syc{L1fe_i5_sh0rt_y0u_n3ed_py7h0n}

normal28

源码:

# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: E:\CTF\Geek-python\python2\python2.py
# Compiled at: 2019-10-22 19:40:16
import struct, time

def fun(start, end, s):
    a = 32310901
    b = 1729
    c = s
    m = end - start#254
    while True:
        d = int((a * c + b) % m)
        yield d
        c = d


if __name__ == '__main__':
    arr = [
     77, 263, 394, 442, 463, 512, 667, 641, 804, 752, 885, 815, 1075, 1059, 1166, 1082, 1429, 1583, 1696, 1380,
     1987, 2263, 2128, 2277, 2387, 2670, 2692, 3255, 3116, 3306, 3132, 3659, 3139, 3422, 3600, 3584, 3343, 3546,
     3299, 3633, 3281, 3146, 2990, 2617, 2780, 2893, 2573, 2584, 2424, 2715, 2513, 2324, 2080, 2293, 2245, 2309,
     2036, 1944, 1931, 1817, 1483, 1372, 1087, 1221, 893, 785, 697, 586, 547, 324, 177, 184]
    flag = raw_input('plz input your flag:')
    length = len(flag)
    a = struct.unpack('<I', flag[length - 4:].encode())[0] & 255
    b = []
    c = fun(1, 255, a)
    for i in range(32):
        b.append(next(c))

    d = [ 0 for i in range(72) ]
    for i in range(length):
        for j in range(32):
            a = ord(flag[i]) ^ b[j]
            d[(i + j)] += a

    for i in range(len(d)):
        if d[i] != arr[i]:
            print 'fail'
            time.sleep(5)
            exit(0)

    print 'success'
    time.sleep(5)
    exit(0)
# okay decompiling normal28.pyc

大概是根据flag%254生成一个数列,然后异或搞一下和arr比较
用z3来解决后面异或的部分,然后数列初始值枚举一下

from z3 import *
import time

def fun(start, end, s):
    a=32310901
    b=1729
    c=s
    m=end - start#254
    while True:
        d=int((a * c + b) % m)
        yield d
        c=d
        
def Z3(p):
    s=Solver()
    f=[BitVec(('x%d' % i),8) for i in range(41) ]
    q=[77, 263, 394, 442, 463, 512, 667, 641, 804, 752, 885, 815, 1075, 1059, 1166, 1082, 1429, 1583, 1696, 1380,
           1987, 2263, 2128, 2277, 2387, 2670, 2692, 3255, 3116, 3306, 3132, 3659, 3139, 3422, 3600, 3584, 3343, 3546,
           3299, 3633, 3281, 3146, 2990, 2617, 2780, 2893, 2573, 2584, 2424, 2715, 2513, 2324, 2080, 2293, 2245, 2309,
           2036, 1944, 1931, 1817, 1483, 1372, 1087, 1221, 893, 785, 697, 586, 547, 324, 177, 184]

    r=[0 for i in range(72)]
    for i in range(41):
        for j in range(32):
            a=f[i]^p[j]
            r[i+j]+=a

    for i in range(0,72):
        s.add(r[i]==q[i])

    if s.check()==sat:
        model=s.model()
        str=[chr(model[f[i]].as_long().real) for i in range(41)]
        print("".join(str))
        time.sleep(5)
        exit()
    else:
        print("unsat")

if __name__ == "__main__":
    for seed in range(0xff):
        p=[]
        r=fun(1, 255, seed)
        for i in range(32):
            p.append(next(r))
        Z3(p)

normal29

源码

# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: E:/Syclover/python3.py
# Compiled at: 2019-11-03 13:29:35
from unicorn import *
from unicorn import arm_const as ac
import time

def Unicorn(input):
    bytescode = b'\x08\xb0-\xe5\x04\xe0\x8d\xe5\x04\xb0\x8d\xe2\x10\xd0M\xe2\x10\x00\x0b\xe5\x14\x10\x0b\xe5\x000\xa0\xe3\x080\x0b\xe5\x000\xa0\xe3\x080\x0b\xe5\x1b\x00\x00\xea\x080\x1b\xe5\x010\x03\xe2\x00\x00S\xe3\n\x00\x00\n\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x07 \x82\xe2r \xef\xe6\x00 \xc3\xe5\t\x00\x00\xea\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x04 \x82\xe2r \xef\xe6\x00 \xc3\xe5\x080\x1b\xe5\x010\x83\xe2\x080\x0b\xe5\x080\x1b\xe5\x1e\x00S\xe3\xe0\xff\xff\xda\x000\xa0\xe3\x080\x0b\xe5\x17\x00\x00\xea\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x000\xd3\xe5\x0c0\x0b\xe5\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x10 \x82\xe2\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x00 \xc3\xe5\x080\x1b\xe5\x100\x83\xe2\x10 \x1b\xe5\x030\x82\xe0\x0c \x1b\xe5r \xef\xe6\x00 \xc3\xe5\x080\x1b\xe5\x010\x83\xe2\x080\x0b\xe5\x080\x1b\xe5\x0e\x00S\xe3\xe4\xff\xff\xda\x000\xa0\xe3\x080\x0b\xe5\x17\x00\x00\xea\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x000\xd3\xe5\x0c0\x0b\xe5\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x01 \x82\xe2\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x00 \xc3\xe5\x080\x1b\xe5\x010\x83\xe2\x10 \x1b\xe5\x030\x82\xe0\x0c \x1b\xe5r \xef\xe6\x00 \xc3\xe5\x080\x1b\xe5\x020\x83\xe2\x080\x0b\xe5\x080\x1b\xe5\x1d\x00S\xe3\xe4\xff\xff\xda\x140\x1b\xe5\x00\x00S\xe3\x01\x00\x00\x1a\x010\xa0\xe3\x04\x00\x00\xea\x140\x1b\xe5\x010C\xe2\x03\x10\xa0\xe1\x10\x00\x1b\xe5\x8f\xff\xff\xeb\x03\x00\xa0\xe1\x04\xd0K\xe2\x00\xb0\x9d\xe5\x04\xd0\x8d\xe2\x04\xf0\x9d\xe4'
    cmp_data = [149, 187, 165, 189, 151, 176, 171, 165, 114, 180, 176, 161, 115, 181, 155, 174, 117, 163, 174, 115, 187, 161, 163, 175, 163, 116, 115, 176, 169, 99, 185]

    def hook_code(mu, address, size, user_data):
        if address == BASE + 420:
            data = mu.mem_read(0, 31)
            if [ data[i] for i in range(len(data)) ] == cmp_data:
                print 'success'
                time.sleep(5)
                exit(0)
            else:
                print 'fail'
                time.sleep(5)
                exit(0)

    mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
    BASE = 4194304
    STACK_ADDR1 = 0
    STACK_ADDR2 = 1024
    STACK_SIZE = 1048576
    mu.mem_map(BASE, 1048576)
    mu.mem_map(STACK_ADDR1, STACK_SIZE)
    mu.mem_write(STACK_ADDR1, input.encode())#写入输入到栈地址0处
    mu.reg_write(ac.UC_ARM_REG_R0, 0) #栈地址存放在r0寄存器中,参数1
    mu.reg_write(ac.UC_ARM_REG_R1, 11)#0xB放入r1寄存器中,参数2
    mu.reg_write(ac.UC_ARM_REG_SP, STACK_ADDR2 - 1)
    mu.mem_write(BASE, bytescode)
    mu.hook_add(UC_HOOK_CODE, hook_code)
    mu.emu_start(BASE, BASE + 424)


if __name__ == '__main__':
    input = raw_input('plz input your flag:')
    Unicorn(input)
# okay decompiling normal29.pyc

用到了unicorn
https://bbs.pediy.com/thread-253868.htm
https://www.anquanke.com/post/id/95199#h2-18
先把bytescode生成二进制文件

def write(path,bytes):
    file = open(path,'wb')
    file.write(bytes)
    file.close()

if __name__ == "__main__":
    bytescode = b'\x08\xb0-\xe5\x04\xe0\x8d\xe5\x04\xb0\x8d\xe2\x10\xd0M\xe2\x10\x00\x0b\xe5\x14\x10\x0b\xe5\x000\xa0\xe3\x080\x0b\xe5\x000\xa0\xe3\x080\x0b\xe5\x1b\x00\x00\xea\x080\x1b\xe5\x010\x03\xe2\x00\x00S\xe3\n\x00\x00\n\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x07 \x82\xe2r \xef\xe6\x00 \xc3\xe5\t\x00\x00\xea\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x04 \x82\xe2r \xef\xe6\x00 \xc3\xe5\x080\x1b\xe5\x010\x83\xe2\x080\x0b\xe5\x080\x1b\xe5\x1e\x00S\xe3\xe0\xff\xff\xda\x000\xa0\xe3\x080\x0b\xe5\x17\x00\x00\xea\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x000\xd3\xe5\x0c0\x0b\xe5\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x10 \x82\xe2\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x00 \xc3\xe5\x080\x1b\xe5\x100\x83\xe2\x10 \x1b\xe5\x030\x82\xe0\x0c \x1b\xe5r \xef\xe6\x00 \xc3\xe5\x080\x1b\xe5\x010\x83\xe2\x080\x0b\xe5\x080\x1b\xe5\x0e\x00S\xe3\xe4\xff\xff\xda\x000\xa0\xe3\x080\x0b\xe5\x17\x00\x00\xea\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x000\xd3\xe5\x0c0\x0b\xe5\x080\x1b\xe5\x10 \x1b\xe5\x030\x82\xe0\x08 \x1b\xe5\x01 \x82\xe2\x10\x10\x1b\xe5\x02 \x81\xe0\x00 \xd2\xe5\x00 \xc3\xe5\x080\x1b\xe5\x010\x83\xe2\x10 \x1b\xe5\x030\x82\xe0\x0c \x1b\xe5r \xef\xe6\x00 \xc3\xe5\x080\x1b\xe5\x020\x83\xe2\x080\x0b\xe5\x080\x1b\xe5\x1d\x00S\xe3\xe4\xff\xff\xda\x140\x1b\xe5\x00\x00S\xe3\x01\x00\x00\x1a\x010\xa0\xe3\x04\x00\x00\xea\x140\x1b\xe5\x010C\xe2\x03\x10\xa0\xe1\x10\x00\x1b\xe5\x8f\xff\xff\xeb\x03\x00\xa0\xe1\x04\xd0K\xe2\x00\xb0\x9d\xe5\x04\xd0\x8d\xe2\x04\xf0\x9d\xe4'
    write("D:/python3",bytescode)

然后拖进IDA32,

按C反汇编

一个简单的递归,传参分别是flag和11
脚本

def dfs(a,n):
    s=""
    s1=""
    s2=""
    for i in range(0,30,2):
        s+=a[i+1]
        s+=a[i]
    s+=a[30]
    s1+=s[16:]+s[15]+s[:15]
    for i in range(31):
        if(i%2):
            s2+=chr(ord(s1[i])-7)
        else:
            s2+=chr(ord(s1[i])-4)
    if(n==0):
        print(s2)
        return
    dfs(s2, n - 1)

if __name__ == "__main__":
    a=[149,187,165,189,151,176,171,165,114,180,176,161,115,181,155,174,117,163,174,115,187,161,163,175,163,116,115,176,169,99,185]
    dfs("".join(map(chr,a)),11)
# Syc{Unic0rn_1s_r3al1y_ama21ng!}

normal31

前置条件是MessageBoxA已被hook
在字符串窗口找到success字符串,找引用没在main里,应该是这一部分被hook掉了

然后跳到AddVectoredExceptionHandler执行指针Handler所指向的函数

中间是sm4的密钥处理,SetUnhandledExceptionFilter(TopLevelExceptionFilter),这个API叫设置异常捕获函数
参数:lpTopLevelExceptionFilter ,函数指针。当异常发生时,且程序不处于调试模式(在vs或者别的调试器里运行)则首先调用该函数。
返回值:返回以前设置的回调函数。
又回到那个被hook住的MessageBoxW函数下方执行那个sm4加密

执行完了sm4加密之后,异常发生,又会回调到刚才SetUnhandledExceptionFilter设置的异常捕获函数的参数lpTopLevelExceptionFilter指针所指向的函数中继续执行
继续往下,发现Str又被改了

BASE64的编码表最终是yzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwx

from pysm4 import decrypt

#-------base64-----------------
diy_baes = 'yzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/abcdefghijklmnopqrstuvwx!'
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
cipher = "1UTAOIkpyOSWGv/mOYFY4R!!"
new_cipher4 = ""
for i in range(0,len(cipher),2):
    new_cipher4 += cipher[i+1]
    new_cipher4 += cipher[i]
new_cipher = ""
for i in range(len(new_cipher4)):
    new_cipher += base[diy_baes.find(new_cipher4[i])]
print(new_cipher)
#-------base64-----------------

#--------cipher_num-------------
byte = new_cipher.decode("base64")
cipher_num = ""
for i in range(len(byte)):
    cipher_num += "%2x"%(ord(byte[i]))
cipher_num = int(cipher_num.replace(' ','0'),base=16)
print(cipher_num)
#--------cipher-------------

#-----------key_num----------
str = "where_are_u_now?"
key_num = ""
for i in range(len(str)):
    key_num +=  "%x"%(ord(str[i]))
key_num = int(key_num,base=16)
print(key_num)
#-----------key----------


clear_num = decrypt(cipher_num, key_num)
print(hex(clear_num)[2:-1].decode('hex'))
#WdCVKQ3yQAYU9I0naQaHTg==
#119384314703134531538573762305905297230
#158720187958446400518369106772618082111
#SM4foRExcepioN?!

normal32

动态的时候F5两次可以把main里没编译出来的部分搞出来,不知道为啥……

这里是一个异或
然后进入加密函数




然后原样转回去,v36那里不知道为啥提取不出来hex,手动把负数转了一下

import struct
b=""
f=""
s="SWPU_2019_CTF"
r=[0xF80F37B3, 0x5DAEBCBC, 0x864D5ABA, 0xD3629744, 0x1624BA4F, 0x1A729F0B, 0x266D6865, 0x67C86BBA]
# r=[-133220429,1571732668,-2041750854,-748513468,371505743,443719435,644704357,1741188026]
a=[0xCA3E0C86, 0x19AED798, 0xA66B77E2, 0xB077A16A, 0x05379169, 0x307BF97A, 0x104B5A43, 0x28D47D86]
for i in range(8):
    b+=str(struct.pack("<L",r[i]^a[i]),encoding="utf8")#编码!
for i in range(len(b)):
    f+=chr(ord(b[i])^ord(s[i%len(s)]))
print(f)
#flag{Y0uaretheB3st!#@_VirtualCC}

posted on 2021-07-30 19:49  diakla  阅读(277)  评论(0)    收藏  举报