2020-网络安全公益赛-writeup-RE

  1. easyvm
  2. easyencrypt
  3. 吃鸡神器
  4. Code2
  5. Analysis of viruses
  6. 奇怪的安装包
  7. 42
  8. veryeasyRE
  9. babymac
  10. factory

easyvm

虚拟机,虽然并不难,不过还是用angr直接秒了

import angr

proj = angr.Project("./vm",auto_load_libs=False)

st = proj.factory.entry_state()
sm = proj.factory.simulation_manager(st)
sm.explore(find=0x400b73, avoid=0x400b81)

print(sm.found[0].posix.dumps(0))

1582515771061

flag{vm_is_not_easy}

easyencrypt

ollvm混淆,不过找关键字符串就能找到地方,AES-ECB加密,key在内存中就有,只能加密十六个字节,后面全是明文,flag是个png文件,前16个字节恢复过来就行。

from Crypto.Cipher import AES

with open("flag.lck") as f:
    tmp = f.read()

end = tmp[16:]
tmp = tmp[:16]
print len(end), len(tmp)

key = 'thisisthekey!!!!'
cipher = AES.new(key, AES.MODE_ECB)
res = cipher.decrypt(tmp)

with open("res", "a+") as r:
    r.write(res+end)

#print cipher.decrypt()

1582515660580

flag{3ff32148-e229-41fd-b7b9-d09e76d35daf}

吃鸡神器

QT程序,这个我是在ida里一个个函数找,发现0x402150是关键函数。然后OD调到对应位置,输入lubenwei,“abcd”,在经过一些处理后有加密结果,怎么加密的并不用关注,只要看到最后的比较过程就可以了。看到此时EDI是我们的输入转化而成,EAX就是对应的结果,直接输入这段结果就行。

1582516740847

1582516899907

flag{41d26f00}

Code2

程序逻辑大致为把输入进行处理作为key,然后对一段密文进行xxtea解密。其他的部分并不用关心,因为这些本来就不是我们控制的。

sub_7FF6E5231890找到对key进行判断的算法,只要让其绕过you are wrong!这里就行了,后面的不用关注。

对算法模拟,爆破找到key

# from pwn import *
# import struct

a = "AB AA AA 3E 39 8E E3 3D 39 8E 63 3E 39 8E E3 3D 39 8E E3 3D 39 8E E3 3D"
a2 = "00 00 00 00 AB AA AA 3E 39 8E E3 3E AB AA 2A 3F 72 1C 47 3F 39 8E 63 3F"


xmm1 = ['0x3eaaaaab', '0x3de38e39', '0x3e638e39', '0x3de38e39', '0x3de38e39', '0x3de38e39']
xmm2 = ['0x0', '0x3eaaaaab', '0x3ee38e39', '0x3f2aaaab', '0x3f471c72', '0x3f638e39']
f1, f2 = [], []

f1 = [0.33333334326744, 0.11111111193895, 0.22222222387791, 0.11111111193895, 0.11111111193895, 0.11111111193895]
f2 = [0.0, 0.33333334326744, 0.44444444775581, 0.66666668653488,0.77777779102325, 0.88888889551163]
print(f1)
print(f2)

t = "8ab697"

def calc(ctx):
    res = 0.0
    v1 = 1.0
    for i in ctx:
        tmp = v1
        #v1 = v1 * f1[t.index(i)-1]
        #res += tmp * f2[t.index(i)-1]
        v1 = v1 * f1[t.index(i)]
        res += tmp * f2[t.index(i)]
    return res

def find_key():
    res = 0.0
    ctx = ""
    for i1 in t:
        for i2 in t:
            for i3 in t:
                for i4 in t:
                    for i5 in t:
                        for i6 in t:
                            for i7 in t:
                                for i8 in t:
                                    for i9 in t:
                                        ctx = i1+i2+i3+i4+i5+i6+i7+i8+i9
                                        ctx = ctx.replace(" ", "")
                                        res = calc(ctx)
                                        if abs(res-0.129556) <= 0.000001:
                                            print ctx

find_key()

其实有好多结果,在最后输出结果之后下断点,一个一个尝试,最后发现8ab86897是正确的

1582515976960

flag{8ab86897-25c9-811a-ce9a-18547ae6801e}

Analysis of viruses

模拟DNA序列的一些操作,其实是在做简单的单表替换。最后的结果都是在堆里面用单向链表连接的。

最后三个字符一组会产生固定的字符串,但是固定的字符串对应的输入可能有多个,这里需要爆破。

from hashlib import md5

b = "Met Cys Leu Ala Arg Leu Phe Ser Ile Leu Asn Val Cys Gly Lys Leu"
def re2(c):
    l1 = "AUGC"
    l2 = "UACG"
    res = ""
    for i in c:
        res += l1[l2.index(i)]
    return res

def ap(a):
    res = []
    res.append(a+"A")
    res.append(a+"U")
    res.append(a+"C")
    res.append(a+"G")
    return res

r = []
r.append(["UAC"])
r.append(["ACA","ACG"])
r.append(ap("GA")+["AAC", "AAU"])
r.append(ap("CG"))
r.append(ap("GC"))
r.append(ap("GA")+["AAC", "AAU"])
r.append(["AAA","AAG"])
r.append(ap("AG"))
r.append(["UAA", "UAG", "UAU"])
r.append(ap("GA")+["AAC", "AAU"])
r.append(["UUA","UUG"])
r.append(ap("CA"))
r.append(["ACA", "ACG"])
r.append(ap("CC"))
r.append(["UUU", "UUC"])
r.append(ap("GA")+["AAC", "AAU"])
r.append(["UAA", "UAG", "UGA"])

# brute
# for i0 in r[0]:
# ...
# if md5(xxx).hexdigest()[0:8] == "e03657e0":
#

这个写得有点粗糙,可能有的情况被不小心遗漏了,而且速度很慢了,反正我是没爆破出来,不过确实是这么做的,因为一开始题目给前6位md5的时候,可以爆出来好多组结果。。

flag{AUGUGCCUUGCAAGACUUUUCUCGAUACUUAACGUCUGUGGAAAACUUUAA}

奇怪的安装包

安装过程中会要求输入密码,不过即使错误也可以解压,解压后的文件是NES模拟器,就是PC机上模拟FC游戏的,还带了个赤色要塞文件hhh,应该是在安装包里搞了一些操作,有点难调。

后来发现这个东西叫NSIS,file命令可查,用1505的7zip就可以提出来脚本,

key是明文,不过也没啥用:

NSIISSOEASY

脚本跟汇编很像,所以没那么难理解:

Function func_429
  Pop $9
  StrCpy $3 ""
  StrCpy $0 $9
  StrCpy $1 0
label_433:
  StrCpy $2 $0 1 $1
  StrCmp $2 "" label_443
  Push $2
  Call func_445
  Pop $2
  IntOp $2 $2 ^ 1
  IntFmt $2 %c $2
  IntOp $1 $1 + 1
  StrCpy $3 $3$2
  Goto label_433
label_443:
  Push $3
FunctionEnd


Function func_445
  Exch $0
    ; Push $0
    ; Exch
    ; Pop $0
  Push $1
  Push $2
  StrCpy $2 1
label_451:
  IntFmt $1 %c $2
  StrCmpS $1 $0 0 label_455
  StrCpy $0 $2
  Goto label_458
label_455:
  IntOp $2 $2 + 1
  StrCmp $2 255 0 label_451
  StrCpy $0 0
label_458:
  Pop $2
  Pop $1
  Exch $0
    ; Push $0
    ; Exch
    ; Pop $0
FunctionEnd

第二个函数在我眼里基本啥也没干,应该是想实现字符转ascii码把,所以其实就是简单的异或1而已:

a = '''gm`fzd787`7bb,g72d,592b,8`g1,cg96813e8d``|'''
flag = ""
for i in a:
    flag += chr((ord(i))^1)
print flag

flag{e696a6cc-f63e-483c-9af0-bf87902d9eaa}

42

因为SEH的机制,IDA的F5会显示得很奇怪:

1582523576885

不过看反汇编的代码可以看到代码的逻辑,loc_4154A1应该是函数的主要逻辑,OD里可以调试,注意这里会先弹出hook再跳转到这里。

说实话,逆了很久才逆明白,程序要求输入格式是:flag{xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx},里面是uuid格式,第一部分和第二部分各少一个字节。

我把算法还原了,这里处理的是uuid格式识别之后的数据:

magic = "3nder5tandf10@t"
mem = []

# s is input
# s = "bd60d0456d311ea93f497358c3c6bc"

i, j = 0, 0
s_len = len(s)
print s_len
for i in range(0, s_len, 2):
    mem.append(int(s[i:i+2], 16)^ord(magic[j]))
    # i += 2
    j += 1

print map(hex, mem), len(mem)

num = []

def g1(i, ax, cx):
    tmp = mem[i:i+5]
    tmp.reverse()
    a = tmp[0]+(tmp[1]<<8)+(tmp[2]<<16)+(tmp[3]<<24)
    b = tmp[4]
    num.append(a ^ ax)
    num.append(b ^ cx)

g1(0, 0x76BDF08F, 0x0FEE1DEAF)
g1(5, 0x846F5F42, 0x11DC37D)
g1(10, 0x14031D68, 0x2cc5d9)

print map(hex, num)

r = ((num[0]+(num[1]<<32))**3)&0xffffffffffffffff
r += ((num[2]+(num[3]<<32))**3)&0xffffffffffffffff
r += ((num[4]+(num[5]<<32))**3)&0xffffffffffffffff
r = r&0xffffffffffffffff

print r
if r == 42:
    print "right"
else:
    print "error"

我这个是按照它这个32位逻辑一点点逆的,还原的时候直接按照64位处理就行。

关于42立方和问题,早就被玩烂了:

42=(-80538738812075974)^3 + 80435758145817515^3 + 12602123297335631^3

写出最终脚本:

a = -80538738812075974&0xffffffffffffffff
b = 80435758145817515&0xffffffffffffffff
c = 12602123297335631&0xffffffffffffffff


a = a^0x0FEE1DEAF76BDF08F
b = b^0x11DC37D846F5F42
c = c^0x2cc5d914031D68

a = hex(a)[2:-1].decode("hex")
b = hex(b)[2:-1].decode("hex")
c = hex(c)[2:-1].decode("hex")

magic = "3nder5tandf10@t"
flag = ""
j = 0

for i in a:
    flag += chr(ord(i)^ord(magic[j]))
    j += 1
for i in b:
    flag += chr(ord(i)^ord(magic[j]))
    j += 1
for i in c:
    flag += chr(ord(i)^ord(magic[j]))
    j += 1

flag = flag.encode("hex")
res =  "flag{"+flag[:7]+"-"+flag[7:11]+"-"+flag[11:15]
res += "-"+flag[15:19]+"-"+flag[19:]+"}"
print res

flag{ed82ab5-5c7a-da78-b7a8-d2f5fbef453}

veryeasyRE

输入长度为0x35

28163746738936845178453226739434617961829429853594162

abcdef12345612345611118888888888

首先会进行插入,插入规则:

mem = dword_427000[0x50]
aa = "" # 输入
j = 0
for i in range(0x50):
    if mem[i] == 0:
        mem[i] = ord(aa[j]) - 0x30
        j += 1

之后每九个字符进行一次检测,分析完可以确定输入只能是0-9数字,且每九个字符不重复,这应该是数独把。找了个解数独的程序一跑,非常快:

import time
t0=time.time()
class point:
    def __init__(self,x,y):
        self.x=x
        self.y=y
        self.available=[]
        self.value=0

def rowNum(p,sudoku):
    row=set(sudoku[p.y*9:(p.y+1)*9])
    row.remove(0)
    return row #set type

def colNum(p,sudoku):
    col=[]
    length=len(sudoku)
    for i in range(p.x,length,9):
        col.append(sudoku[i])
    col=set(col)
    col.remove(0)
    return col #set type

def blockNum(p,sudoku):
    block_x=p.x//3
    block_y=p.y//3
    block=[]
    start=block_y*3*9+block_x*3
    for i in range(start,start+3):
        block.append(sudoku[i])
    for i in range(start+9,start+9+3):
        block.append(sudoku[i])
    for i in range(start+9+9,start+9+9+3):
        block.append(sudoku[i])
    block=set(block)
    block.remove(0)
    return block #set type

def initPoint(sudoku):
    pointList=[]
    length=len(sudoku)
    for i in range(length):
        if sudoku[i]==0:
            p=point(i%9,i//9)
            for j in range(1,10):
                if j not in rowNum(p,sudoku) and j not in colNum(p,sudoku) and j not in blockNum(p,sudoku):
                    p.available.append(j)
            pointList.append(p)
    return pointList


def tryInsert(p,sudoku):
    availNum=p.available
    for v in availNum:
        p.value=v
        if check(p,sudoku):
            sudoku[p.y*9+p.x]=p.value
            if len(pointList)<=0:
                t1=time.time()
                useTime=t1-t0
                showSudoku(sudoku)
                print('\nuse Time: %f s'%(useTime))
                exit()
            p2=pointList.pop()
            tryInsert(p2,sudoku)
            sudoku[p2.y*9+p2.x]=0
            sudoku[p.y*9+p.x]=0
            p2.value=0
            pointList.append(p2)
        else:
            pass    

def check(p,sudoku):
    if p.value==0:
        print('not assign value to point p!!')
        return False
    if p.value not in rowNum(p,sudoku) and p.value not in colNum(p,sudoku) and p.value not in blockNum(p,sudoku):
        return True
    else:
        return False

def showSudoku(sudoku):
    for j in range(9):
        for i in range(9):
            print('%d '%(sudoku[j*9+i]),end='')
        print('')    

if __name__=='__main__':
    sudoku = [0, 0, 5, 0, 9, 4, 0, 0, 0,\
        0, 0, 1, 5, 0, 0, 2, 0, 9,\
        0, 7, 0, 2, 0, 0, 0, 0, 1,\
        0, 9, 0, 0, 0, 0, 0, 0, 6,\
        8, 0, 0, 0, 0, 0, 1, 0, 5,\
        5, 0, 0, 0, 2, 0, 0, 0, 8,\
        0, 0, 0, 3, 5, 0, 0, 7, 0,\
        7, 4, 0, 0, 0, 6, 0, 1, 0,\
        3, 0, 0, 0, 0, 7, 8, 0, 0]
    pointList=initPoint(sudoku)
    showSudoku(sudoku)
    print('\n')
    p=pointList.pop()
    tryInsert(p,sudoku)

输入结果,还真通过了。所以第一部分的结果为:

28163746738936845178453226739434617961829429853594162

babymac

虽然买不起mac,不过程序逻辑还是挺清晰的。处理一下基本等于源代码:

1582555736774

1582555751576

写爆破脚本就完事了,等就硬等:

a = [0x0000000000000001, 0x00000000000001FE, 0x0000000000001A79, 0x0000000000004940, 0x000000000000712F, 0x000000000000E1C5, 0x000000000001E866, 0x000000000003B85C, 0x00000000000760B0, 0x00000000000ED95D, 0x00000000001DB360, 0x00000000003B4D46, 0x000000000076A007, 0x0000000000ED528C, 0x0000000001DA9434, 0x0000000003B51CEA, 0x00000000076A592D, 0x000000000ED4AA88, 0x000000001DA951A4, 0x000000003B529EF7, 0x0000000076A55442, 0x00000000ED4AB07B, 0x00000001DA9560A0, 0x00000003B52AACC4, 0x000000076A5553D9, 0x0000000ED4AA997D, 0x0000001DA9553387, 0x0000003B52AA7EED, 0x00000076A554F324, 0x000000ED4AA9E5D7, 0x000001DA9553C9B2, 0x000003B52AA79A0C]
res = [0x00030970372813D2, 0x0002D3A89BCA52AC, 0x00031551E79154A2, 0x0002C522E9A5298A, 0x0002A61367C5C698, 0x000264491C01CAFD, 0x00026CA3A06C98B3, 0x0002DACBD12FB903, 0x0002E470707574E1, 0x000309E5DC39A9A7]


for i in range(32):
    a[i]*=0x10A9FC70042
    a[i]%=0x682669BC19DB

print map(hex, a)

def enc(b):
    res = 0
    for i in range(32):
        res += a[31-i]*(b&1)
        b = b >> 1
    return res

flag = "flag"

import string

d1 = string.letters + string.digits + "_-{}"
d1 = string.printable
#j = 0

def brute(idx):
    for i1 in d1:
        for i2 in d1:
            for i3 in d1:
                for i4 in d1:
                    n = int((i1+i2+i3+i4).encode("hex"), 16)
                    if enc(n) == res[idx]:
                        #print i1+i2+i3+i4
                        return i4+i3+i2+i1
                    else:
                        continue

for i in range(1, len(res)):
    flag += brute(i)
    print flag

flag{m3Rkl3_h3LLMaN_KNaPsacK_Al90R17Hm!}

factory

关键函数都通过多进程信号传递来处理,前面有hash的调试检测,所以不能直接调试,不过可以attach上去。慢慢看出来这是个虚拟机,不过还是逆了很久,IDA里可以做这样的结构体处理:

1582636148648

甚至把它的逻辑用python写出来了,可以辅助分析,直接用效果并不好。

ops = [17, 52, 0, 42, 5, 16, 20, 9, 23, 0, \
    32, 5, 3, 17, 29, 6, 0, 0, 5, 3,\
    17, 64, 6, 0, 64, 5, 17, 29, 23, 14,\
     1, 21, 4, 15, 1, 22, 2, 0, 0, 4, \
 3, 5, 16, 20, 50, 5, 9, 2, 19, 29,\
  5, 18, 21, 4, 16, 20, 61, 10, 1, 19,\
   52, 3, 4, 18, 14, 1, 21, 4, 7, 1,\
   22, 2, 0, 0, 4, 3, 5, 16, 20, 85, 5, 9, 1, 19, 64, 5, 18]

# 0x7fffffffddec: sign [rbp-0x14]
# 0x7ffff7ff7100  stack
# 0x7ffff7ff7000  input
# 0x7ffff7ff7790: arg1
# 0x7ffff7ff7791: arg2
# 0x7ffff7ff7792: arg3
# 0x7ffff7ff7793: sp   [rax+0x13] 
# 0x7ffff7ff7794: rip  [rax+0x14]
# 0x7ffff7ff7795: res  [rax+0x15] 
class VM:
    def __init__(self):
        self.stack = [0]*0x300
        self.flag = [72]*42 + [0]
        self.arg = [0, 0, 0]
        self.sp = 0
        self.ip = 0
        self.res = 0

    def push(self, numb):
        self.stack[self.sp] = numb
        self.sp += 1
        #print "push %d" %numb

    def pop(self, numb):
        self.sp -= 1
        self.arg[numb] = self.stack[self.sp]
        #print self.stack
        print "pop %d to arg%d" %(self.arg[numb], numb+1)

    def Call(self):
        self.stack[self.sp] = self.ip
        self.sp += 1
        self.ip = tmp
        print "call %d" %self.ip
        #print self.ip

    def Ret(self):
        self.sp -= 1
        self.ip = self.stack[self.sp]
        print "ret to %d" %self.ip

    def flag2stack(self):
        self.stack[self.sp] = self.flag[self.arg[2]]
        self.sp += 1
        print "push flag[%d]" %self.arg[2]
        #print self.flag[0]

    def stack2flag(self):
        self.sp -= 1
        self.flag[self.arg[2]] = self.stack[self.sp]
        print "pop to flag[%d]"%self.arg[2]

two_op = [0, 8, 9, 10, 12, 13, 14, 17, 19, 20]

global tmp
vm = VM()

from time import sleep
while True:
    #sleep(0.2)
    op = ops[vm.ip]
    if op == 23:
        print "end"
        break
    vm.ip += 1
    if op in two_op:
        op2 = ops[vm.ip]
        vm.ip += 1
        tmp = op2

    if op == 0:
        vm.push(tmp)
        print "push %d"%tmp
    elif op==1:
        vm.push(vm.arg[0])
        print "push arg1 ==> %d"%vm.arg[0]
    elif op==2:
        vm.push(vm.arg[1])
        print "push arg2 ==> %d"%vm.arg[1]
    elif op==3:
        vm.push(vm.arg[2])
        print "push idx ==> %d"%vm.arg[2]
    elif op==4:
        vm.pop(0)
    elif op==5:
        vm.pop(1)
    elif op==6:
        vm.pop(2)

    elif op==7:
        vm.arg[0] += vm.arg[1]
        print "arg1 = arg1+arg2"
    elif op==8:
        vm.arg[0] += tmp
        print "arg1 += %d" %tmp
    elif op==9:
        vm.arg[1] += tmp
        print "arg2 += %d" %tmp
    elif op==10:
        vm.arg[2] += tmp
        print "idx += %d" %tmp
    elif op==11:
        vm.arg[0] -= vm.arg[1]
        print "arg1 = arg1-arg2"
    elif op==12:
        vm.arg[0] -= tmp
        print "arg1 -= %d" %tmp
    elif op==13:
        vm.arg[1] -= tmp
        print "arg2 -= %d" %tmp
    elif op==14:
        vm.arg[2] -= tmp
        print "idx -= %d" %tmp
    elif op==15:
        vm.arg[0] ^= vm.arg[1]
        print "arg1 = arg1^arg2"
    elif op==16:
        vm.res = (vm.arg[0]==vm.arg[1])
        print "if arg1==arg2:res=1"
        #print vm.res
    elif op==17:
        vm.Call()
    elif op==18:
        vm.Ret()
    elif op==19:  # jmp
        vm.ip = tmp
        print "jmp %d" %tmp
    elif op==20:  # if jmp
        if vm.res == 1 :
            vm.ip = tmp
            print "if res: jmp %d" %tmp
        else:
            print "else"
    elif op==21:
        vm.flag2stack()
    elif op==22:
        vm.stack2flag()
    else:
        print "illegal"
        break

逆了很久的过程,主要是没什么经验,中间走了点弯路:

a = [17, 52, 0, 42, 5, 16, 20, 9, 23, 0, \
    32, 5, 3, 17, 29, 6, 0, 0, 5, 3,\
    17, 64, 6, 0, 64, 5, 17, 29, 23, 14,\
     1, 21, 4, 15, 1, 22, 2, 0, 0, 4, \
 3, 5, 16, 20, 50, 5, 9, 2, 19, 29,\
  5, 18, 21, 4, 16, 20, 61, 10, 1, 19,\
   52, 3, 4, 18, 14, 1, 21, 4, 7, 1,\
   22, 2, 0, 0, 4, 3, 5, 16, 20, 85, 5, 9, 1, 19, 64, 5, 18]

#0: 
# 17, 52,
call 52, 

# 长度等于42,跳到9,否则结束
#2:
# 0, 42, 5, 16, 20, 9, 23
arg2 = 42
if arg1==arg2: jmp 9, 
else:end

# Main 函数,调用了三段加密函数
#9: 
# 0,32, 5, 3, 17, 29, 
# 6, 0, 0, 5, 3, 17, 64, 
# 6, 0, 64, 5, 17, 29, 23,
arg2 = 32
push idx
call 29

pop idx
arg2 = 0
push idx
call 64

pop idx
arg2 = 64
call 29
end

# 异或处理,传入的arg2需要有初值,每次+2
#29: 
# 14,1, 21, 4, 15, 1, 22, 
# 2, 0, 0, 4, 3, 5, 16, 20, 50, 
# 5, 9, 2, 19, 29
idx -= 1
arg1 = flag[idx]
flag[idx] = arg1 ^ arg2

push arg2
if idx=0:jmp 50

pop arg2
arg2 += 2
jmp 29


#50:
# 5, 18
pop arg2
ret

# 可以计算出输入的长度
#52:
# 21, 4, 16, 20, 61, 10, 1, 19, 52, 
arg1 = flag[idx]

if arg1==arg2:
   jmp 61
idx += 1
jmp 52

# arg1获得idx,返回2
#61:
# 3, 4, 18, 
arg1 = idx
ret

# 相减处理,arg2有初值,每次+1
#64:
# 14, 1, 21, 4, 7, 1, 22, 2, 0, 0, 4, 3, 5, 
# 16, 20, 85, 5, 9, 1, 19, 64
idx -= 1
arg1 = flag[idx]
arg1 += arg2
flag[idx] = arg1

push arg2
arg1 = 0
arg2 = idx

if arg1 == arg2:
    jmp 85

pop to arg2
arg2 += 1
jmp 64


#85:
# 5, 18
pop arg2
ret

根据加密规则实现解密即可:

res = [0xAF, 0xD4, 0xB8, 0xBD, 0xBC, 0xB9, 0xFC, 0xF1, 0xF6, 0xA1, 0xF5, 0xFE, 0xF1, 0xE9, 0x0B, 0xF3, 0x22, 0x0F, 0x14, 0xE2, 0xED, 0xE5, 0xE2, 0x1F, 0x56, 0x54, 0x4B, 0x3A, 0x7E, 0x3E, 0x5A, 0x5A, 0x5D, 0x0B, 0x6B, 0x68, 0x54, 0x54, 0x64, 0x07, 0x51, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

def enc(flag):
    j = 0
    for i in range(0, 42, 1)[::-1]:
        ord(flag[i])^(32+j)
        j += 2

    k = 0
    for i in range(0, 42, 1)[::-1]:
        ord(flag[i])+k
        k += 1

    m = 0
    for i in range(0, 42, 1)[::-1]:
        ord(flag[i])^(64+m)
        m += 2

def dec(res):
    flag = res

    m = 0
    for i in range(0, 42, 1)[::-1]:
        flag[i] = flag[i]^(64+m)
        m += 2

    k = 0
    for i in range(0, 42, 1)[::-1]:
        flag[i] = flag[i]-k
        k += 1

    j = 0
    for i in range(0, 42, 1)[::-1]:
        flag[i] = flag[i]^(32+j)
        j += 2
    return flag

l = dec(res)
print "".join([chr(i) for i in l])

flag{e171a284-49e7-4817-ad8d-b704c02309e0}


connect 1037178204@qq.com

文章标题:2020-网络安全公益赛-writeup-RE

本文作者:t1an5t

发布时间:2020-02-26, 23:01:00

最后更新:2020-02-29, 21:52:38

原始链接:http://yoursite.com/2020-%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E5%85%AC%E7%9B%8A%E8%B5%9B-writeup-RE/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录