2019年7月23日做题笔记(CyBRICS的一道逆向题Matreshka)

题目

前些日子打了CyBRICS CTF国际赛,被虐哭。写篇笔记,记录下一些题目,这道Matreshka考察了java,go,python的基本逆向知识,涉及简单的加密算法,难度不是很大,首先是题目给了一个Code2.class文件和一个data.bin文件,可以直接将class反编译成java源码,看下代码逻辑:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;

class Code2
{
  Code2() {}
  
  public static byte[] decode(byte[] paramArrayOfByte, String paramString) throws Exception
  {
    SecretKeyFactory localSecretKeyFactory = SecretKeyFactory.getInstance("DES");
    byte[] arrayOfByte1 = paramString.getBytes();
    javax.crypto.spec.DESKeySpec localDESKeySpec = new javax.crypto.spec.DESKeySpec(arrayOfByte1);
    javax.crypto.SecretKey localSecretKey = localSecretKeyFactory.generateSecret(localDESKeySpec);
    Cipher localCipher = Cipher.getInstance("DES");
    localCipher.init(2, localSecretKey);
    byte[] arrayOfByte2 = localCipher.doFinal(paramArrayOfByte);
    return arrayOfByte2;
  }
  
  public static byte[] encode(byte[] paramArrayOfByte, String paramString) throws Exception { SecretKeyFactory localSecretKeyFactory = SecretKeyFactory.getInstance("DES");
    byte[] arrayOfByte1 = paramString.getBytes();
    javax.crypto.spec.DESKeySpec localDESKeySpec = new javax.crypto.spec.DESKeySpec(arrayOfByte1);
    javax.crypto.SecretKey localSecretKey = localSecretKeyFactory.generateSecret(localDESKeySpec);
    Cipher localCipher = Cipher.getInstance("DES");
    localCipher.init(1, localSecretKey);
    byte[] arrayOfByte2 = localCipher.doFinal(paramArrayOfByte);
    return arrayOfByte2;
  }
  
  public static void main(String[] paramArrayOfString) throws Exception {
    String str = "matreha!";
    byte[] arrayOfByte1 = encode(System.getProperty("user.name").getBytes(), str);
    byte[] arrayOfByte2 = { 76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18 };
    for (int i = 0; i < arrayOfByte2.length; i++) {
      if (arrayOfByte2[i] != arrayOfByte1[i]) {
        System.out.println("No");
        return;
      }
    }
    java.io.File localFile = new java.io.File("data.bin");
    FileInputStream localFileInputStream = new FileInputStream(localFile);
    byte[] arrayOfByte3 = new byte[(int)localFile.length()];
    localFileInputStream.read(arrayOfByte3);
    localFileInputStream.close();
    byte[] arrayOfByte4 = decode(arrayOfByte3, System.getProperty("user.name"));
    FileOutputStream localFileOutputStream = new FileOutputStream("stage2.bin");
    localFileOutputStream.write(arrayOfByte4, 0, arrayOfByte4.length);
    localFileOutputStream.flush();
    localFileOutputStream.close();
  }
}

可以看出这段用了DES算法对字符串进行encode,密钥key为matreha!,如果和结果和byte[] arrayOfByte2 = { 76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18 };相同则继续将bin文件使用这段字符串进行decode操作,保存成stage2.bin文件,所以我们需要知道这段字符串的真正内容,只需要使用密钥matreha!直接decode这段byte[] arrayOfByte2 = { 76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18 };即可。
完整代码如下所示:

package test;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.Base64.Encoder;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;

public class Code2
{
  Code2() {}
  
  public static byte[] decode(byte[] paramArrayOfByte, String paramString) throws Exception
  {
    SecretKeyFactory localSecretKeyFactory = SecretKeyFactory.getInstance("DES");
    byte[] arrayOfByte1 = paramString.getBytes();
    javax.crypto.spec.DESKeySpec localDESKeySpec = new javax.crypto.spec.DESKeySpec(arrayOfByte1);
    javax.crypto.SecretKey localSecretKey = localSecretKeyFactory.generateSecret(localDESKeySpec);
    Cipher localCipher = Cipher.getInstance("DES");
    localCipher.init(2, localSecretKey);
    byte[] arrayOfByte2 = localCipher.doFinal(paramArrayOfByte);
    return arrayOfByte2;
  }
  
  public static byte[] encode(byte[] paramArrayOfByte, String paramString) throws Exception { SecretKeyFactory localSecretKeyFactory = SecretKeyFactory.getInstance("DES");
    byte[] arrayOfByte1 = paramString.getBytes();
    javax.crypto.spec.DESKeySpec localDESKeySpec = new javax.crypto.spec.DESKeySpec(arrayOfByte1);
    javax.crypto.SecretKey localSecretKey = localSecretKeyFactory.generateSecret(localDESKeySpec);
    Cipher localCipher = Cipher.getInstance("DES");
    localCipher.init(1, localSecretKey);
    byte[] arrayOfByte2 = localCipher.doFinal(paramArrayOfByte);
    return arrayOfByte2;
  }
  
  public static void main(String[] paramArrayOfString) throws Exception {
    String str = "matreha!";
    byte[] arrayOfByte1 = encode("lettreha".getBytes(), str);
    byte[] arrayOfByte2 = { 76, -99, 37, 75, -68, 10, -52, 10, -5, 9, 92, 1, 99, -94, 105, -18 };
    byte[] arrayOfByte7 = decode(arrayOfByte2, str);
    String s = new String(arrayOfByte7);
    for (int i = 0; i < arrayOfByte2.length; i++) {
      if (arrayOfByte2[i] == arrayOfByte1[i]) {
        System.out.println(s);
        return;
      }
    }
    java.io.File localFile = new java.io.File("data.bin");
    FileInputStream localFileInputStream = new FileInputStream(localFile);
    byte[] arrayOfByte3 = new byte[(int)localFile.length()];
    localFileInputStream.read(arrayOfByte3);
    localFileInputStream.close();
    byte[] arrayOfByte4 = decode(arrayOfByte3, "lettreha");
    FileOutputStream localFileOutputStream = new FileOutputStream("stage2.bin");
    localFileOutputStream.write(arrayOfByte4, 0, arrayOfByte4.length);
    localFileOutputStream.flush();
    localFileOutputStream.close();
  }
}

可以得出真正的密钥为lettreha,替换掉System.getProperty("user.name"),可以得到stage2.bin,根据文件头可以看出是一个elf可执行文件,直接扔入IDA,分析一下就可以找到关键跳转:


IDA

将这第一个跳转改为jnz,第二个跳转改为jmp就可以直接进入写入文件,可以得到第三个文件,是一个pyc文件,需要反编译出py源码,我用的是uncompyle6.exe:

# uncompyle6 version 3.2.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)]
# Embedded file name: ./1.py
# Size of source mod 2**32: 439 bytes
def decode(data, key):
    idx = 0
    res = []
    for c in data:
        res.append(chr(c ^ ord(key[idx])))
        idx = (idx + 1) % len(key)

    return res

flag = [
 40, 11, 82, 58, 93, 82, 64, 76, 6, 70, 100, 26, 7, 4, 123, 124, 127, 45, 1, 125, 107, 115, 0, 2, 31, 15]
print('Enter key to get flag:')
key = input()
if len(key) != 8:
    print('Invalid len')
    quit()
res = decode(flag, key)
print(''.join(res))
# okay decompiling result.pyc

可以看出是一个简单的按位异或加密,可以根据flag的开头是cybrics{来轻易得到密钥,从而得到最终flag,解题脚本如下:

def decode(data, key):
    idx = 0
    res = []
    for c in data:
        res.append(chr(c ^ ord(key[idx])))
        idx = (idx + 1) % len(key)
    return res

flag = [40, 11, 82, 58, 93, 82, 64, 76, 6, 70, 100, 26, 7, 4, 123, 124, 127, 45, 1, 125, 107, 115, 0, 2, 31, 15]

key=''
a="cybrics{"
for i in range(8):
    key+=chr(flag[i]^ord(a[i]))
print key

res = decode(flag, key)
print(''.join(res))

最后得到flag为:


flag
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容