美文网首页CTF
2018Xman夏令营re题wp

2018Xman夏令营re题wp

作者: Killshadow | 来源:发表于2018-09-03 00:13 被阅读0次

    1. crackme

    package com.j.crackme;
    
    import android.content.pm.ApplicationInfo;
    import android.content.res.AssetManager;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    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 com.j.ctz.IMyClass;
    import dalvik.system.DexClassLoader;
    import java.io.BufferedOutputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MainActivity
      extends AppCompatActivity
    {
      private Class clazz = null;
      
      private void a()
      {
        if (this.clazz == null)
        {
        // 调用c方法
          if (!c()) {
            return;
          }
          Object localObject = new StringBuilder();
          ((StringBuilder)localObject).append(getApplicationInfo().dataDir);
          ((StringBuilder)localObject).append(File.separator);
          ((StringBuilder)localObject).append("files");
          ((StringBuilder)localObject).append(File.separator);
          ((StringBuilder)localObject).append("plugin.jar");
          localObject = new File(((StringBuilder)localObject).toString()).getAbsolutePath();
          String str = getApplicationInfo().dataDir;
          try
          {
            DexClassLoader localDexClassLoader = new dalvik/system/DexClassLoader;
            localDexClassLoader.<init>((String)localObject, str, null, getClassLoader());
            // 加载plugin.jar里的class给clazz
            this.clazz = localDexClassLoader.loadClass("com.j.base.MyClass");
          }
          catch (Exception localException)
          {
            localException.printStackTrace();
            return;
          }
        }
      }
      // c方法功能:先对每个字节异或,再传入plugin.jar
      private boolean c()
      {
        try
        {
        // 调用d方法
          byte[] arrayOfByte = d(getAssets().open("plugin"));
          if (arrayOfByte == null) {
            return false;
          }
          // 每个字节异或0xEF
          for (int i = 0; i < arrayOfByte.length; i++) {
            arrayOfByte[i] = ((byte)(byte)(arrayOfByte[i] ^ 0xEF));
          }
          BufferedOutputStream localBufferedOutputStream = new java/io/BufferedOutputStream;
          localBufferedOutputStream.<init>(openFileOutput("plugin.jar", 0));
          // 再写入到plugin.jar
          localBufferedOutputStream.write(arrayOfByte);
          localBufferedOutputStream.flush();
          localBufferedOutputStream.close();
          return true;
        }
        catch (Exception localException)
        {
          localException.printStackTrace();
        }
        return false;
      }
      // d方法功能:传入一个数据流, 将其转换为字节数组
      public byte[] d(InputStream paramInputStream)
      {
        try
        {
          ByteArrayOutputStream localByteArrayOutputStream = new java/io/ByteArrayOutputStream;
          localByteArrayOutputStream.<init>();
          byte[] arrayOfByte = new byte[1024];
          for (;;)
          {
            int i = paramInputStream.read(arrayOfByte);
            if (i == -1) {
              break;
            }
            localByteArrayOutputStream.write(arrayOfByte, 0, i);
          }
          localByteArrayOutputStream.flush();
          localByteArrayOutputStream.close();
          paramInputStream.close();
          paramInputStream = localByteArrayOutputStream.toByteArray();
        }
        catch (IOException paramInputStream)
        {
          paramInputStream.printStackTrace();
          paramInputStream = null;
        }
        return paramInputStream;
      }
      
      protected void onCreate(Bundle paramBundle)
      {
        super.onCreate(paramBundle);
        setContentView(2131296283);
        ((Button)findViewById(2131165218)).setOnClickListener(new View.OnClickListener()
        {
          public void onClick(View paramAnonymousView)
          {
            // 调用a方法
            MainActivity.this.a();
            EditText localEditText = (EditText)MainActivity.this.findViewById(2131165234);
            paramAnonymousView = localEditText.getText().toString();
            if (MainActivity.this.clazz != null) {
              try
              {
              // 经过Myclass加密之后,再base64encode
                if 
             (Base64.encodeToString(((IMyClass)MainActivity.this.clazz.newInstance()).check(paramAnonymousView), 0).equals("+sfQ39PX3eGOzOGNyt/Kj90=\n"))
                {
                  Toast.makeText(MainActivity.this.getApplicationContext(), "Good job", 0).show();
                  localEditText.setText(String.format("flag{%s}", new Object[] { paramAnonymousView }));
                }
                else
                {
                  Toast.makeText(MainActivity.this.getApplicationContext(), "Why you say so", 0).show();
                }
              }
              catch (Exception paramAnonymousView)
              {
                paramAnonymousView.printStackTrace();
                return;
              }
            }
          }
        });
      }
    }
    
    

    程序生成plugin.jar之后直接从/data/data/$(packagename)/找到plugin.jar , 代码如下:

    package com.j.base;
    
    import com.j.ctz.IMyClass;
    
    public class MyClass implements IMyClass {
        public MyClass() {
            super();
        }
        // 只是做了简单的异或操作
        public byte[] check(String arg4) {
            byte[] v0 = arg4.getBytes();
            int v1;
            for(v1 = 0; v1 < v0.length; ++v1) {
                v0[v1] = ((byte)(v0[v1] ^ 190));
            }
    
            return v0;
        }
    }
    
    import base64
    print ''.join(map(lambda x:chr(ord(x)^190), list(base64.b64decode("+sfQ39PX3eGOzOGNyt/Kj90="))))
    

    flag:

    Flag{Dynamic_0r_3tat1c}
    

    2.hiddendata

    思路: Java层没做什么处理, 直接调用so层的check函数. 分析so层, 发现main函数没做什么处理, 分析onLoad能得到结果.

    #-*-coding = utf-8-*-
    ori = [0x41, 0xFF, 0xF3, 0xDB, 0x06, 0xB3, 0x69, 0xC2, 0x90, 0xA3, 
      0x21, 0x8F, 0x7B, 0x6D, 0x32, 0x8C]
    
    keys = [0x56, 0xFC, 0xD8, 0x66]
    
    final = [0x64, 0x32, 0x4A, 0xCD, 0x34, 0xE6, 0x5D, 0x82, 0xB6, 0x53, 
      0x0B, 0x39, 0xC8, 0xE7, 0x21, 0x71]
    
    after = [i for i in range(len(final))]
    
    v = [i for i in range(len(final))]
    flag = ""
    for i in range(len(after)):
        key = keys[i % 4];
        v[i] = ((((ori[i] >> i % 4) | (ori[i] << i / 4)) & 0xff) ^ key ^ final[i])
        flag += chr(v[i])
    print flag
    

    python脚本比较坑的一点要注意: 左移的时候可能大于32位(int 是32位) 即64bit. 所以要与上0xff.

    import sys
    i = sys.maxint
    print i # 查看int变量的最大值
    

    3. hide

    #coding=utf-8
    import struct
    import string
    def u32(data):
        return struct.unpack("<I",data)[0]
     
    def p32(data):
        return struct.pack("<I",data)
     
    def u64(data):
        return struct.unpack("<Q",data)[0]
     
    def p64(data):
        return struct.pack("<Q",data)
     
    input1 = '1234567890123456'
    input1 = bytearray(input1)
    CONST_STR = 's1IpP3rEv3Ryd4Y3'
    CONST = 0X676E696C
    v4 = 0
    v4_4=0
    v4_4_arr = [0 for i in range(0,9)]
    for i in range(1,9):
        v4_4_arr[i] = (v4_4_arr[i-1]+CONST)&0XFFFFFFFF
     
    def re_block(byte_arr_8):
        i = 0
        v3 = u32(byte_arr_8[0:4])
        v4 = u32(byte_arr_8[4:8])
        print 'round', v3, v4
        for i in range(7,-1,-1):
            v30 = (v3 << 4) & 0xffffffff
            v2c = v3 >> 5
            edx = v30 ^ v2c
            v30 = (v3 + edx) & 0xffffffff
     
            v28 = (v4_4_arr[i+1] >> 11) & 3
            edx = u32(CONST_STR[v28 * 4:(v28 + 1) * 4])
            v2c = (v4_4_arr[i+1] + edx) & 0xffffffff  # xxxx
            # print 'v2c',hex(v2c)
            print v30 ^ v2c
            v4 = (v4+0x100000000-(v30 ^ v2c)) & 0xffffffff
     
            v30 = (v4 << 4) & 0xffffffff
            v2c = v4 >> 5
            edx = v30 ^ v2c
     
            v30 = (v4 + edx) & 0xffffffff
     
            v28 = v4_4_arr[i] & 3
            edx = u32(CONST_STR[v28 * 4:(v28 + 1) * 4])
            v2c = (v4_4_arr[i] + edx) & 0xffffffff
     
            v3 = (v3+0x100000000-(v30 ^ v2c)) & 0xffffffff
     
            print 'round',i,v3,v4
        byte_arr_8[0:4] = p32(v3)
        byte_arr_8[4:8] = p32(v4)
        return byte_arr_8
    def xor16(byte_arr_16):
        for i in range(0,16):
            byte_arr_16[i]^=i
    def re_all(str16):
        byte_arr = bytearray(str16)
        xor16(byte_arr)#传入整个bytearray,就是传入地址
        byte_arr[0:8] = re_block(byte_arr[0:8])#传入部分bytearray,就是复制之后再传入
        byte_arr[8:16] = re_block(byte_arr[8:16])
        xor16(byte_arr)
        byte_arr[0:8] = re_block(byte_arr[0:8])
        byte_arr[8:16] = re_block(byte_arr[8:16])
        xor16(byte_arr)
        byte_arr[0:8] = re_block(byte_arr[0:8])
        byte_arr[8:16] = re_block(byte_arr[8:16])
        return str(byte_arr)
     
     
    def block(str8):
        i=0
        input1=bytearray(str8)
        v3 = u32(input1[8 * i:8 * i + 4])
        v4 = u32(input1[8 * i + 4:8 * (i + 1)])
        v4_4 = 0  ##0000
        for j in range(0, 8):
     
            v30 = (v4 << 4) & 0xffffffff
            v2c = v4 >> 5
            edx = v30 ^ v2c
     
            v30 = (v4 + edx) & 0xffffffff
     
            v28 = v4_4 & 3
            edx = u32(CONST_STR[v28 * 4:(v28 + 1) * 4])
            v2c = (v4_4 + edx) & 0xffffffff
     
            v3 = ((v30 ^ v2c) + v3) & 0xffffffff
     
     
            v4_4 = (v4_4 + CONST) & 0xffffffff
     
            v30 = (v3 << 4) & 0xffffffff
            v2c = v3 >> 5
            edx = v30 ^ v2c
            v30 = (v3 + edx) & 0xffffffff
     
            v28 = (v4_4 >> 11) & 3
            edx = u32(CONST_STR[v28 * 4:(v28 + 1) * 4])
            v2c = (v4_4 + edx) & 0xffffffff  # xxxx
            print v30 ^ v2c
            v4 = ((v30 ^ v2c) + v4) & 0xffffffff
     
            print 'round', j, v3, v4
     
        input1[8 * i:8 * i + 4] = p32(v3)
        input1[8 * i + 4:8 * (i + 1)] = p32(v4)
        str8_1=str(input1)
        return str8_1
    def block2(str8):
        input1 = bytearray(str8)
        for i in range(0,8):
            input1[i]=input1[1]^i
        return str(input1)
    des = ('52B8137F358CF21B'+'F46386D2734F1E31').decode('hex')
    print len(des)
     
    print block('12345678').encode('hex')
    des1 = '5b90ef3f91b58fe6'.decode('hex')
    print re_all(bytearray(des))
    
    

    4. re0_0

    for循环是解密
    解密之后就能正常F5
    解密之后可看到逻辑简单
    
    # import idc_bytes
    # buf = ida_bytes.get_bytes(0x600B00, 182)
    # patch = ""
    # for i in buf:
    #   patch += chr(ord(i) ^ 0x0C)
    # ida_bytes.patch_bytes(0x600B00,patch)
    
    enc = [0x66, 0x6D, 0x63, 0x64, 0x7F, 0x6B, 0x37, 0x64, 0x3B, 0x56, 0x60, 0x3B, 0x6E, 0x70]
    flag = ""
    for i in range(len(enc)):
        flag += chr(i ^ enc[i])
    print flag
    

    5. re1_0

    思路: 找到关键比较下断读寄存器或直接patch

    6. EVR

    思路: 爆破

    1533210933799.png
    flag_enc = [30,  21,   2,  16,  13,  72,  72, 111, 221, 221, 72, 100,  99, 215,  46,  44, 254, 106, 109,  42, 242, 111, 154,  77, 139,  75,  10, 138,  79,  69, 23,  70,  79,  20,  11]
    flag=""
    for i in range(7):
        flag += chr(flag_enc[i]^0x76)
    for i in range(7):
        for j in range(32,127):
            a = j ^ 0x76 ^ 0xad
            a = (2 * a) & 0xaa | (( a & 0xaa) >> 1) 
            if(a==flag_enc[i+7]):
                flag += chr(j)
    for i in range(7):
        for j in range(32,127):
            a = j ^ 0x76 ^ 0xbe
            a = (4 * a) & 0xcc | (( a & 0xcc) >> 2) 
            if(a==flag_enc[i+14]):
                flag += chr(j)
    for i in range(7):
        for j in range(32,127):
            a = j ^ 0x76 ^ 0xef
            a = (16 * a) & 0xf0 | (( a & 0xf0) >> 4) 
            if(a==flag_enc[i+21]):
                flag += chr(j)
    for i in range(7):
        flag += chr(flag_enc[i+28]^0x76)
    print flag
    

    7. Magic

    https://4hou.win/wordpress/?p=20989

    https://www.52pojie.cn/thread-742361-1-1.html

    8. apl

    apl语言非常简介,当然,看他也像看天书一样.

    简介: https://zh.wikipedia.org/wiki/APL%E8%AA%9E%E8%A8%80

    https://monosource.github.io/writeup/2018/05/08/plaidctf-aplunatics/

    ⎕IO←0⋄'BIE°?½>IL½E.!!<E!:E84¥¸²E23Å8»968'{{⍵(~⍵)/'success' 'fail'}⊃(+/⍺= 13+{+/⍵/⌽2*⍳⍴⍵}¨,/33 8⍴(8×⍴⍵)⍴7⌽⍉(-⌊(⍴'f0xtr0t')÷2)⌽⍉11 24⍴∊{a≠8↑(0,a←(8⍴2)⊤⍵)}¨⌽⎕⎕UCSUCS ⍵)=⍴⍺}'INPUT HERE'
    

    ⎕IO←0⋄是多余的.

    相关文章

      网友评论

        本文标题:2018Xman夏令营re题wp

        本文链接:https://www.haomeiwen.com/subject/ndbvwftx.html