无标点日记

void __cdecl __noreturn sub_401190(char *a1)
{
  int v1; // [esp+4Ch] [ebp-Ch]
  signed int i; // [esp+54h] [ebp-4h]

  if ( strlen(a1) == 16 )
  {
    for ( i = 0; i < 16; ++i )
    {
      v1 = i + a1[i] - unk_432A60[i] + 19;      // i + input[i] - byte[i] + 19
      if ( v1 <= 0 )
      {
        sub_40100F(OhhMywifewaslost);           // OhhMywifewaslost
      }
      else if ( OhhMywifewaslost[i] != unk_432A73[v1] )
      {
        sub_40100F(OhhMywifewaslost);
      }
    }
  }
  sub_401005();
}

sub_40100F对字符串"OhhMywifewaslost"进行操作。

根据用户输入的16个字符,判断每个字符对应的v1是否进行加密。

puzzle = [0x00,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A]
Oh = 'OhhMywifewaslost'
aaaa = [ 0x29, 0x6A, 0x68, 0x46, 0x66, 0x5B, 0x67, 0x7D, 0x6F, 0x6D, 0x77, 0x62, 0x76, 0x28, 0x25, 0x25]
flag = ''
for i in range(0,16):
    for inputs in range(0,255):
        v = i + inputs - aaaa[i] + 19
        if v > 0 and v < len(puzzle):
            if puzzle[v] == ord(Oh[i]):
                flag += chr(inputs)
                print(flag)

// Iheardascream!!!                

"Iheardascream!!!"字符串的每一位都表示不经过sub_40100F

C:\Users\Bufsnake\Desktop>puzzle.exe
Iheardaloudnoise
and Iheardascream!!!
get{OhhMywifewaslost}

所以可以在此基础上控制"OhhMywifewaslost"是否经过sub_40100F,以及经过的次数.

# 加密一次的情况
C:\Users\Bufsnake\Desktop>puzzle.exe
Iheardaloudnoise
and Iheardascream!!a
get{Wearecockroaches}
# 加密二次的情况
C:\Users\Bufsnake\Desktop>puzzle.exe
Iheardaloudnoise
and Iheardascream!aa
get{甧皽?{嵵r稾l?蛚
...

Flag:flag{Wearecockroaches}

flag是好长好长的一段数字

主活动代码如下

package com.example.myapplication;

import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    /* renamed from: e */
    String f32e;

    /* access modifiers changed from: protected */
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView((int) C0274R.layout.activity_main);
        final EditText editText = (EditText) findViewById(C0274R.C0276id.text);
        final EditText editText2 = (EditText) findViewById(C0274R.C0276id.text1);
        Button button = (Button) findViewById(C0274R.C0276id.button1);
        ((Button) findViewById(C0274R.C0276id.button)).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                if (MainActivity.this.check(editText.getText().toString())) {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "用户名正确!", 1).show();
                } else {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "用户名错误!!", 1).show();
                }
            }
        });
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                String obj = editText2.getText().toString();
                MainActivity mainActivity = MainActivity.this;
                if (mainActivity.check2(obj, mainActivity.f32e)) {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "success!!", 1).show();
                } else {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "defeated!", 1).show();
                }
            }
        });
    }

    /* access modifiers changed from: 0000 */
    public boolean check(String str) {
        if (str.length() == 0) {
            return false;
        }
        String lowerCase = Base64.encodeToString(str.getBytes(), 0).toLowerCase();
        this.f32e = lowerCase;
        if (lowerCase.substring(3, 9).equals("dqy1ba")) {
            return true;
        }
        return false;
    }

    /* access modifiers changed from: 0000 */
    public boolean check2(String str, String str2) {
        String str2HexStr = str2HexStr(str2);
        StringBuilder sb = new StringBuilder();
        sb.append(str2HexStr);
        sb.append(str);
        return checkcode(sb.toString()).equals("5731d798714022433553234173");
    }

    public String checkcode(String str) {
        String[] strArr = new String[15];
        try {
            strArr[0] = str.substring(0, 2);
            strArr[1] = str.substring(2, 4);
            strArr[2] = str.substring(4, 6);
            strArr[3] = str.substring(6, 8);
            strArr[4] = str.substring(8, 10);
            strArr[5] = str.substring(10, 12);
            strArr[6] = str.substring(12, 14);
            strArr[7] = str.substring(14, 16);
            strArr[8] = str.substring(16, 18);
            strArr[9] = str.substring(18, 20);
            strArr[10] = str.substring(20, 22);
            strArr[11] = str.substring(22, 24);
            strArr[12] = str.substring(24, 26);
            strArr[13] = str.substring(26, 28);
            strArr[14] = str.substring(28, 30);
        } catch (Exception unused) {
        }
        String str2 = BuildConfig.FLAVOR;
        String str3 = str2;
        for (int i = 0; i < 14; i++) {
            if (i == 0) {
                str3 = xor(strArr[i], strArr[i + 1]);
                StringBuilder sb = new StringBuilder();
                sb.append(str2);
                sb.append(str3);
                str2 = sb.toString();
            } else {
                str3 = xor(str3, strArr[i]);
                StringBuilder sb2 = new StringBuilder();
                sb2.append(str2);
                sb2.append(str3);
                str2 = sb2.toString();
            }
        }
        return str2;
    }

    private static String xor(String str, String str2) {
        String binaryString = Integer.toBinaryString(Integer.valueOf(str, 16).intValue());
        String binaryString2 = Integer.toBinaryString(Integer.valueOf(str2, 16).intValue());
        String str3 = "0";
        if (binaryString.length() != 8) {
            for (int length = binaryString.length(); length < 8; length++) {
                StringBuilder sb = new StringBuilder();
                sb.append(str3);
                sb.append(binaryString);
                binaryString = sb.toString();
            }
        }
        if (binaryString2.length() != 8) {
            for (int length2 = binaryString2.length(); length2 < 8; length2++) {
                StringBuilder sb2 = new StringBuilder();
                sb2.append(str3);
                sb2.append(binaryString2);
                binaryString2 = sb2.toString();
            }
        }
        String str4 = BuildConfig.FLAVOR;
        for (int i = 0; i < binaryString.length(); i++) {
            if (binaryString2.charAt(i) == binaryString.charAt(i)) {
                StringBuilder sb3 = new StringBuilder();
                sb3.append(str4);
                sb3.append(str3);
                str4 = sb3.toString();
            } else {
                StringBuilder sb4 = new StringBuilder();
                sb4.append(str4);
                sb4.append("1");
                str4 = sb4.toString();
            }
        }
        Log.e("code", str4);
        return Integer.toHexString(Integer.parseInt(str4, 2));
    }

    public static String str2HexStr(String str) {
        char[] charArray = "0123456789abcdef".toCharArray();
        StringBuilder sb = new StringBuilder(BuildConfig.FLAVOR);
        byte[] bytes = str.getBytes();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(charArray[(bytes[i] & 240) >> 4]);
            sb.append(charArray[bytes[i] & 15]);
        }
        return sb.toString().trim();
    }
}

通过dqy1ba中的qy1b解密得到C-A结合比赛名称与出题者,可得知用户名为ISCC-AiQiong,并且由于ISCC-AiQiong经过加密后长度足够长,导致checkcode的时候不会判断注册码是否正确,只会判断用户名,无论输入什么注册码都会成功。但不知道flag到底是个啥。

后来更新了题目附件

package com.example.myapplication;

import android.os.Bundle;
import android.util.Base64;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    /* renamed from: e */
    String f32e;

    /* access modifiers changed from: protected */
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView((int) C0274R.layout.activity_main);
        final EditText editText = (EditText) findViewById(C0274R.C0276id.text);
        final EditText editText2 = (EditText) findViewById(C0274R.C0276id.text1);
        Button button = (Button) findViewById(C0274R.C0276id.button1);
        ((Button) findViewById(C0274R.C0276id.button)).setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                if (MainActivity.this.check(editText.getText().toString())) {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "用户名正确!", 1).show();
                } else {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "用户名错误!!", 1).show();
                }
            }
        });
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View view) {
                if (MainActivity.this.check2(editText2.getText().toString())) {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "success!!", 1).show();
                } else {
                    Toast.makeText(MainActivity.this.getApplicationContext(), "defeated!", 1).show();
                }
            }
        });
    }

    /* access modifiers changed from: 0000 */
    public boolean check(String str) {
        if (str.length() == 0) {
            return false;
        }
        String lowerCase = Base64.encodeToString(str.getBytes(), 0).toLowerCase();
        this.f32e = lowerCase;
        if (lowerCase.substring(3, 9).equals("dqy1ba")) {
            return true;
        }
        return false;
    }

    /* access modifiers changed from: 0000 */
    public boolean check2(String str) {
        return checkcode(str2HexStr(str)).equals("23243673763173613543db");
    }

    public String checkcode(String str) {
        String[] strArr = new String[15];
        try {
            strArr[0] = str.substring(0, 2);
            strArr[1] = str.substring(2, 4);
            strArr[2] = str.substring(4, 6);
            strArr[3] = str.substring(6, 8);
            strArr[4] = str.substring(8, 10);
            strArr[5] = str.substring(10, 12);
            strArr[6] = str.substring(12, 14);
            strArr[7] = str.substring(14, 16);
            strArr[8] = str.substring(16, 18);
            strArr[9] = str.substring(18, 20);
            strArr[10] = str.substring(20, 22);
            strArr[11] = str.substring(22, 24);
            strArr[12] = str.substring(24, 26);
            strArr[13] = str.substring(26, 28);
            strArr[14] = str.substring(28, 30);
        } catch (Exception unused) {
        }
        String str2 = BuildConfig.FLAVOR;
        String str3 = str2;
        for (int i = 0; i < 15; i++) {
            if (i == 0) {
                str3 = xor(strArr[i], strArr[i + 1]);
                StringBuilder sb = new StringBuilder();
                sb.append(str2);
                sb.append(str3);
                str2 = sb.toString();
            } else {
                str3 = xor(str3, strArr[i]);
                StringBuilder sb2 = new StringBuilder();
                sb2.append(str2);
                sb2.append(str3);
                str2 = sb2.toString();
            }
        }
        return str2;
    }

    private static String xor(String str, String str2) {
        String binaryString = Integer.toBinaryString(Integer.valueOf(str, 16).intValue());
        String binaryString2 = Integer.toBinaryString(Integer.valueOf(str2, 16).intValue());
        String str3 = "0";
        if (binaryString.length() != 8) {
            for (int length = binaryString.length(); length < 8; length++) {
                StringBuilder sb = new StringBuilder();
                sb.append(str3);
                sb.append(binaryString);
                binaryString = sb.toString();
            }
        }
        if (binaryString2.length() != 8) {
            for (int length2 = binaryString2.length(); length2 < 8; length2++) {
                StringBuilder sb2 = new StringBuilder();
                sb2.append(str3);
                sb2.append(binaryString2);
                binaryString2 = sb2.toString();
            }
        }
        String str4 = BuildConfig.FLAVOR;
        for (int i = 0; i < binaryString.length(); i++) {
            if (binaryString2.charAt(i) == binaryString.charAt(i)) {
                StringBuilder sb3 = new StringBuilder();
                sb3.append(str4);
                sb3.append(str3);
                str4 = sb3.toString();
            } else {
                StringBuilder sb4 = new StringBuilder();
                sb4.append(str4);
                sb4.append("1");
                str4 = sb4.toString();
            }
        }
        return Integer.toHexString(Integer.parseInt(str4, 2));
    }

    public static String str2HexStr(String str) {
        char[] charArray = "0123456789abcdef".toCharArray();
        StringBuilder sb = new StringBuilder(BuildConfig.FLAVOR);
        byte[] bytes = str.getBytes();
        for (int i = 0; i < bytes.length; i++) {
            sb.append(charArray[(bytes[i] & 240) >> 4]);
            sb.append(charArray[bytes[i] & 15]);
        }
        return sb.toString().trim();
    }
}

改动还挺大

image-20200504004413633

用户名还是输入ISCC-AiQiong,但是用户名输入的这次改变不了注册码。

23243673763173613543db长度为22,因为加密后的结果如果为0x0b,则只会返回’b’字符,需要填充8个0,但是不知道填在哪8个位置。

import z3

solve = z3.Solver()
s = []
for i in range(0,15):
    s.append(z3.BitVec('s[%d]'%i,8))

# 23243673763173613543db

for i in s:
    solve.add(i >= ord('0'))
    solve.add(i <= ord('9'))
solve.add(s[0] ^ s[1] == 2)   // 因为都为数字,所以第一位和第二位 xor 得到的结果肯定小于0xf
solve.add(2 ^ s[1] == 0x32)   // 逐步探测 0x32 或 0x3
solve.add(0x32 ^ s[2] == 0x4) // 发现规律,0,2,4,6...需要在前面添加'0'
solve.add(0x4 ^ s[3] == 0x36)
solve.add(0x36 ^ s[4] == 0x7)
solve.add(0x7 ^ s[5] == 0x37)
solve.add(0x37 ^ s[6] == 0x6)
solve.add(0x6 ^ s[7] == 0x31)
solve.add(0x31 ^ s[8] == 0x7)
solve.add(0x7 ^ s[9] == 0x36)
solve.add(0x36 ^ s[10] == 0x1)
solve.add(0x1 ^ s[11] == 0x35)
solve.add(0x35 ^ s[12] == 0x4)
solve.add(0x4 ^ s[13] == 0x3d)
solve.add(0x3d ^ s[14] == 0xb)
solve.add(s[0] ^ s[1] ^ s[1] ^ s[2] ^ s[3] ^ s[4] ^ s[5] ^ s[6] ^ s[7] ^ s[8] ^ s[9] ^ s[10] ^ s[11] ^ s[12] ^ s[13] ^ s[14] == 0xb)
if solve.check() == z3.sat:
    for i in range(0,15):
        print(solve.model()[s[i]],",",end='')

print('')
flag = [50 ,48 ,54 ,50 ,49 ,48 ,49 ,55 ,54 ,49 ,55 ,52 ,49 ,57 ,54]
print(''.join(chr(i) for i in flag))
// flag{206210176174196}

苏大强的保险箱-01

In [1]: b = [0xD5, 0x9E, 0xB4, 0x70, 0x78, 0x60, 0x82, 0x70, 0x39, 0x5E]

In [2]: a = [0x0A, 0x07, 0x41, 0x0B, 0x2C, 0x0C, 0x3D, 0x38, 0x27, 0x73]

In [3]: m = []

In [4]: for i in range(len(a)):
   ...:     m.append(b[9-i] -i -a[i])
   ...:

In [5]: m
Out[5]: [84, 49, 45, 116, 48, 103, 45, 117, 111, 89]

In [6]: ''.join(chr(i) for i in m)
Out[6]: 'T1-t0g-uoY'

In [7]: m.reverse()

In [8]: ''.join(chr(i) for i in m)
Out[8]: 'You-g0t-1T'

Never Give Up

文件格式错误,需要修改,经过查阅资料,发现损坏的是dex文件,dex文件有个关键字xV4搜索发现存在两处,修改如下:

image-20200504183507982

使用dex2jar将dex转成jar文件。

使用jadx打开jar文件,如下图,可以成功反编译

image-20200504183652468

image-20200504215457540

分析程序得到

ZIP压缩(AES(SHA256(15431516836),flag)) == "XXXXXXXXXXXD7BA396A2249B7AE45CDC9D09DB16BE5C56DAB147F3CC8172BDF8DAC95545737AB5BB01163F10AA"

可以发现经过zip压缩之后前12个字符是固定的,所以

"78BBA4F709ED7BA396A2249B7AE45CDC9D09DB16BE5C56DAB147F3CC8172BDF8DAC95545737AB5BB01163F10AA"

可以得到

ZIP压缩(AES("890af61d119e419329e5c660d4ec92a850544e101a7142d1b653836fddd942eb",flag)) = "78BBA4F709ED7BA396A2249B7AE45CDC9D09DB16BE5C56DAB147F3CC8172BDF8DAC95545737AB5BB01163F10AA"

解密代码如下

import java.io.UnsupportedEncodingException;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.*;
import java.security.SecureRandom;
import java.io.ByteArrayOutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

public class output {
    public static void main(String[] args){
        byte[] output = new byte[1024];
        output = J(G("78BBA4F709ED7BA396A2249B7AE45CDC9D09DB16BE5C56DAB147F3CC8172BDF8DAC95545737AB5BB01163F10AA"));
        output = decrypt(output,G("890AF61D119E419329E5C660D4EC92A850544E101A7142D1B653836FDDD942EB"));
        for (byte b : output) {
            System.out.print((char)b);
        }
    }
    public static byte[] G(String str) {
        int length = str.length() / 2;
        byte[] bArr = new byte[length];
        for (int i = 0; i < length; i++) {
            bArr[i] = Integer.valueOf(str.substring(i * 2, (i * 2) + 2), 16).byteValue();
        }
        return bArr;
    }

    public static byte[] J(byte[] bArr) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(bArr.length);
        Inflater inflater = new Inflater();
        try {
            inflater.setInput(bArr);
            byte[] bArr2 = new byte[64];
            while (!inflater.finished()) {
                int inflate = inflater.inflate(bArr2);
                if (inflate == 0) {
                    inflater.setDictionary("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes());
                } else {
                    byteArrayOutputStream.write(bArr2, 0, inflate);
                }
            }
        } catch (DataFormatException e) {
            e.printStackTrace();
        } finally {
            inflater.end();
        }
        return byteArrayOutputStream.toByteArray();
    }
    public static byte[] decrypt(byte[] cipherBytes, byte[] key){
        try{
            // 生成密钥对象
            SecretKey secKey = new SecretKeySpec(key, "AES");
            // 获取 aes 密码器
            Cipher cipher = Cipher.getInstance("AES");
            // 初始化密码器(解密模型)
      // 1 是加密模式CIPHER.ENCRYPT_MODE
      // 2 是解密模式CIPHER.DECRYPT_MODE
            cipher.init(2,secKey); // 
            // 解密数据, 返回明文
            return cipher.doFinal(cipherBytes);
        }catch(Exception e) {
            System.out.println("\n"+e);
        }
        byte a[] = {1,2,3};
        return a;
    }
}
// flag{L1r3n5u0xI4n9J15h1}

Obfu

查看函数列表发现encode1,调用其的地址在那9999个函数中,猜测只有它参与了加密,9999个函数只是幌子。

image-20200502211429540

测试在文件中输入32个’1’。

image-20200502211508348

在encode2前下个断点,得到的数据和encode1后得到的数据是相同的。

image-20200502211931405

image-20200502211330739

接下来分析encode2函数

变种的腾讯tea加密 de1ta = 0xdeadbeef

获取当前时间戳,通过以下代码得到key值

v3 = 0;
printf("Your Key %X,But I Can't Give It To You.\n", v0);
result = (v0 ^ 0xDEADBEEF);
v2 = v0 ^ 0xDEADBEEF;
for ( i = 0; i <= 3; ++i )
{
  for ( j = 0; j <= 31; ++j )
    v3 ^= (v2 >> j) & 1;
  v2 = v3 | 2 * v2;
  result = i;
  *(&key + i) = v2;
}

每8位一组将32位加密

for ( k = 0; k <= 31; k += 8 )
  result = EncryptTEA((k + 8605856LL), (k + 4 + 8605856LL), &key);

解密代码如下

def get_key(time):
    key = []
    v2 = time ^ 0xDEADBEEF
    v3 = 0
    for j in range(0,4):
        for k in range(0,32):
            v3 = v3 ^ (v2 >> k) & 1
        v2 = (v3 | (v2 << 1)) & 0xffffffff
        key.append(v2)
    return key

def replace_3_5(byte):
    byte = ((byte >> 5) | (byte << 3)) & 0xff
    return byte

def decode(first,second,key):
    num = (0xdeadbeef << 4) & 0xffffffff
    for i in range(0,16):
        one = (first + num) & 0xffffffff
        two = ((first << 3) + key[2]) & 0xffffffff
        thr = ((first >> 6) + key[3]) & 0xffffffff
        second = (second - (one ^ two ^ thr)) & 0xffffffff
        one = (second + num) & 0xffffffff
        two = ((second << 3) + key[0]) & 0xffffffff
        thr = ((second >> 6) + key[1]) & 0xffffffff
        first = (first - (one ^ two ^ thr))&0xffffffff
        num = (num - 0xdeadbeef) & 0xffffffff
    dec.append(first)
    dec.append(second)

inputs = [0xba,0x7f,0x1c,0xea,0xc0,0x1a,0x4b,0xdf,0x0d,0xb0,0x57,0xb6,0x05,0x27,0x2c,0x80,0x20,0x6a,0x21,0x72,0x54,0x28,0x46,0x68,0x07,0xfe,0x36,0xa3,0xff,0xda,0x60,0x75]
for ti in range(1588266000,1588431600):
    key = get_key(ti)
    for i in range(0,32,8):
        first = int(hex(inputs[i+3])[2:].rjust(2,'0') + hex(inputs[i+2])[2:].rjust(2,'0') + hex(inputs[i+1])[2:].rjust(2,'0') + hex(inputs[i])[2:].rjust(2,'0'),16)
        second = int(hex(inputs[i+7])[2:].rjust(2,'0') + hex(inputs[i+6])[2:].rjust(2,'0') + hex(inputs[i+5])[2:].rjust(2,'0') + hex(inputs[i+4])[2:].rjust(2,'0'),16)
        decode(first,second,key)
    decode_data = []
    for i in range(0,len(dec)):
        temp = hex(dec[i])[2:].rjust(8,'0')
        decode_data.append(int(temp[6:8],16))
        decode_data.append(int(temp[4:6],16))
        decode_data.append(int(temp[2:4],16))
        decode_data.append(int(temp[0:2],16))
    for i in range(len(decode_data)):
        print(chr(replace_3_5(decode_data[i])),end='')
    print('')
    dec = []
# flag{CI3vEr_T0_FlNd_tlMe_sS^Ff!}

需要爆破时间戳,这里从2020-05-01 0:0:0开始爆破 到 2020-05-02 23:0:0,可以爆破到2020-05-02 11:33:15加密的flag,也可以直接得到flag值。

image-20200504000354079

坑点:python 整形、python运算优先级以及大小端问题

苏大强的保险箱-2

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  size_t v4; // rbx
  int v6[12]; // [rsp+20h] [rbp-60h]
  int v7; // [rsp+50h] [rbp-30h]
  int v8; // [rsp+54h] [rbp-2Ch]
  int v9; // [rsp+58h] [rbp-28h]
  int v10; // [rsp+5Ch] [rbp-24h]
  int v11; // [rsp+60h] [rbp-20h]
  int v12; // [rsp+64h] [rbp-1Ch]
  int v13; // [rsp+68h] [rbp-18h]
  int v14; // [rsp+6Ch] [rbp-14h]
  int v15; // [rsp+70h] [rbp-10h]
  int v16; // [rsp+74h] [rbp-Ch]
  int v17; // [rsp+78h] [rbp-8h]
  int v18; // [rsp+7Ch] [rbp-4h]
  unsigned __int8 v19[256]; // [rsp+A0h] [rbp+20h]
  unsigned __int8 v20[256]; // [rsp+1A0h] [rbp+120h]
  char Str2[8]; // [rsp+2A0h] [rbp+220h]
  char Str[16]; // [rsp+2C0h] [rbp+240h]
  char Buffer; // [rsp+2D0h] [rbp+250h]
  unsigned int v24; // [rsp+2F0h] [rbp+270h]
  int j; // [rsp+2F4h] [rbp+274h]
  int v26; // [rsp+2F8h] [rbp+278h]
  int i; // [rsp+2FCh] [rbp+27Ch]

  _main();
  memset(v19, 0, sizeof(v19));
  memset(v20, 0, sizeof(v20));
  printf("Please input the key:", 32i64, v20);
  gets(&Buffer);
  strcpy(Str2, "a1dWT1pJXF1USVxRV1ZbUElQSVBJ");
  if ( !strcmp(&Buffer, Str2) )
  {
    printf("Please input the flag:");
    gets(Str);
    v24 = strlen(Str);
    v3 = strlen(Str2);
    rc4_init(v19, Str2, v3);                    // rc4初始化
    for ( i = 0; i <= 255; ++i )
      v20[i] = v19[i];
    rc4_crypt(v19, Str, v24);                   // 加密flag
    for ( i = 0; ; ++i )
    {
      v4 = i;
      if ( v4 >= strlen(Str) )
        break;
      v6[i] = Str[i];                           // 复制flag
    }
    memset(&v7, 0, 0x50ui64);
    v7 = 0xFFFFFF9D;
    v8 = 0xFFFFFF87;
    v9 = 0x71;
    v10 = 0xFFFFFFA4;
    v11 = 0xFFFFFF83;
    v12 = 0xB;
    v13 = 0xFFFFFFAA;
    v14 = 0x53;
    v15 = 0xFFFFFFC4;
    v16 = 0x38;
    v17 = 0x36;
    v18 = 0xFFFFFF85;
    v26 = 0;
    for ( j = 0; j <= 11; ++j )                 // 比较flag
    {
      if ( v6[j] != *(&v7 + j) )
        ++v26;
    }
    if ( v26 )
    {
      puts("Wrong!Please try again");
    }
    else
    {                                           // 解密刚刚加密后的flag
      rc4_crypt(v20, Str, v24);
      printf("Congratualtions!The flag is %s\n", Str);
    }
    system("pause");
  }
  else
  {
    printf("Wrong key!Please try again!");
    system("pause");
  }
  return 0;
}

分析可知为Rc4加密,动态调试获得密钥流:

0xCD, 0x87, 0x7D, 0x96, 0x97, 0x0E, 0xAA, 0x05, 0xCC, 0x38, 0x39, 0x83

解密代码如下

In [1]: inputs = "a"*12

In [2]: key = [0xCD, 0x87, 0x7D, 0x96, 0x97, 0x0E, 0xAA, 0x05, 0xCC, 0x38, 0x39, 0x83]

In [3]: enc = [0x9D,0x87,0x71,0xA4,0x83,0xB,0xAA,0x53,0xC4,0x38,0x36,0x85]

In [4]: len(inputs)
Out[4]: 12

In [5]: len(key)
Out[5]: 12

In [6]: len(enc)
Out[6]: 12

In [7]: for i in range(0,12):
   ...:     print(chr(ord('a') ^ key[i] ^ enc[i]))
   ...:
1
a
m
S
u
d
a
7
i
a
n
g

In [8]: s = ''
   ...: for i in range(0,12):
   ...:     s += (chr(ord('a') ^ key[i] ^ enc[i]))
   ...:     print(s)
   ...:
1
1a
1am
1amS
1amSu
1amSud
1amSuda
1amSuda7
1amSuda7i
1amSuda7ia
1amSuda7ian
1amSuda7iang

flag:flag{1amSuda7iang}

….



ctf      iscc re

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!