[buuctf.reverse] 11-32

目录

11 java逆向解密

012_[GXYCTF2019]luck_guy

013_刮开有奖

014_[BJDCTF2020]JustRE

015_findit

016_简单注册器

017_[GWCTF 2019]pyre

018_[ACTF新生赛2020]easyre

019_rsa

020_[ACTF新生赛2020]rome

021_CrackRTF

022_[FlareOn4]login

023_[2019红帽杯]easyRE

024_[GUET-CTF2019]re

025_[WUSTCTF2020]level1

026_[SUCTF2019]SignIn

027_[MRCTF2020]Transform

028_[WUSTCTF2020]level2

029_[ACTF新生赛2020]usualCrypt

030_Youngter-drive

031_相册

032_[HDCTF2019]Maze


011_java逆向解密

用jadx打开,看源码

package defpackage;

import java.util.ArrayList;
import java.util.Scanner;

/* renamed from: Reverse reason: default package */
public class Reverse {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        System.out.println("Please input the flag :");
        String str = s.next();
        System.out.println("Your input is :");
        System.out.println(str);
        Encrypt(str.toCharArray());
    }

    public static void Encrypt(char[] arr) {
        ArrayList<Integer> Resultlist = new ArrayList<>();
        for (char c : arr) {
            Resultlist.add(Integer.valueOf((c + '@') ^ 32));
        }
        int[] KEY = {180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65};
        ArrayList<Integer> KEYList = new ArrayList<>();
        for (int valueOf : KEY) {
            KEYList.add(Integer.valueOf(valueOf));
        }
        System.out.println("Result:");
        if (Resultlist.equals(KEYList)) {
            System.out.println("Congratulations!");
        } else {
            System.err.println("Error!");
        }
    }
}

直接给出字符值为+0x40再异或32,解反顺序处理一下

key = [180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
print(bytes([( i^32 + 0xc0)&0xff for i in key ]))
#This_is_the_flag_\xa1
#flag{This_is_the_flag_!}

012_[GXYCTF2019]luck_guy

主函数在get_flag

unsigned __int64 get_flag()
{
  unsigned int v0; // eax
  int i; // [rsp+4h] [rbp-3Ch]
  int j; // [rsp+8h] [rbp-38h]
  __int64 s[5]; // [rsp+10h] [rbp-30h] BYREF
  unsigned __int64 v5; // [rsp+38h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  v0 = time(0LL);
  srand(v0);
  for ( i = 0; i <= 4; ++i )
  {
    switch ( rand() % 200 )
    {
      case 1:
        puts("OK, it's flag:");
        memset(s, 0, sizeof(s));
        strcat((char *)s, f1);
        strcat((char *)s, &f2);
        printf("%s", (const char *)s);
        break;
      case 2:
        printf("Solar not like you");
        break;
      case 3:
        printf("Solar want a girlfriend");
        break;
      case 4:
        strcpy((char *)s, "icug`of\x7F");
        strcat(&f2, (const char *)s);
        break;
      case 5:
        for ( j = 0; j <= 7; ++j )
        {
          if ( j % 2 == 1 )
            *(&f2 + j) -= 2;
          else
            --*(&f2 + j);
        }
        break;
      default:
        puts("emmm,you can't find flag 23333");
        break;
    }
  }
  return __readfsqword(0x28u) ^ v5;
}

这个运行不了,但可以看到先是把给定串按奇偶位处理一下再输出

f2 = '\x7Ffo`guci'[::-1]
f2a = ''
for i in range(8):
    if i%2 == 1:
        f2a += chr(ord(f2[i]) - 2)
    else:
        f2a += chr(ord(f2[i]) - 1)


flag = 'GXY{do_not_'+f2a 
print(flag )
#GXY{do_not_hate_me}
#flag{do_not_hate_me}

013_刮开有奖

程序运行不了,除了sub_4010F0都很容易理解

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi
  const char *v5; // edi
  int v7[2]; // [esp+8h] [ebp-20030h] BYREF
  int v8; // [esp+10h] [ebp-20028h]
  int v9; // [esp+14h] [ebp-20024h]
  int v10; // [esp+18h] [ebp-20020h]
  int v11; // [esp+1Ch] [ebp-2001Ch]
  int v12; // [esp+20h] [ebp-20018h]
  int v13; // [esp+24h] [ebp-20014h]
  int v14; // [esp+28h] [ebp-20010h]
  int v15; // [esp+2Ch] [ebp-2000Ch]
  int v16; // [esp+30h] [ebp-20008h]
  CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
  char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF

  memset(String, 0, 0xFFFFu);
  GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
  if ( strlen(String) == 8 )
  {
    v7[0] = 90;
    v7[1] = 74;
    v8 = 83;
    v9 = 69;
    v10 = 67;
    v11 = 97;
    v12 = 78;
    v13 = 72;
    v14 = 51;
    v15 = 110;
    v16 = 103;
    sub_4010F0((int)v7, 0, 10);
    memset(v18, 0, 0xFFFFu);
    v18[0] = String[5];
    v18[2] = String[7];
    v18[1] = String[6];
    v4 = sub_401000((int)v18, strlen(v18));
    memset(v18, 0, 0xFFFFu);
    v18[1] = String[3];
    v18[0] = String[2];
    v18[2] = String[4];
    v5 = sub_401000((int)v18, strlen(v18));
    if ( String[0] == v7[0] + 34
      && String[1] == v10
      && 4 * String[2] - 141 == 3 * v8
      && String[3] / 4 == 2 * (v13 / 9)
      && !strcmp(v4, "ak1w")
      && !strcmp(v5, "V1Ax") )
    {
      MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
    }
  }
  return 0;
}

sub_4010F0每次选一个最大的放到最后,实际上就是个冒泡

INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
  const char *v4; // esi
  const char *v5; // edi
  int v7[2]; // [esp+8h] [ebp-20030h] BYREF
  int v8; // [esp+10h] [ebp-20028h]
  int v9; // [esp+14h] [ebp-20024h]
  int v10; // [esp+18h] [ebp-20020h]
  int v11; // [esp+1Ch] [ebp-2001Ch]
  int v12; // [esp+20h] [ebp-20018h]
  int v13; // [esp+24h] [ebp-20014h]
  int v14; // [esp+28h] [ebp-20010h]
  int v15; // [esp+2Ch] [ebp-2000Ch]
  int v16; // [esp+30h] [ebp-20008h]
  CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREF
  char v18[65536]; // [esp+10034h] [ebp-10004h] BYREF

  memset(String, 0, 0xFFFFu);
  GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);
  if ( strlen(String) == 8 )
  {
    v7[0] = 90;
    v7[1] = 74;
    v8 = 83;
    v9 = 69;
    v10 = 67;
    v11 = 97;
    v12 = 78;
    v13 = 72;
    v14 = 51;
    v15 = 110;
    v16 = 103;
    sub_4010F0((int)v7, 0, 10);
    memset(v18, 0, 0xFFFFu);
    v18[0] = String[5];
    v18[2] = String[7];
    v18[1] = String[6];
    v4 = sub_401000((int)v18, strlen(v18));
    memset(v18, 0, 0xFFFFu);
    v18[1] = String[3];
    v18[0] = String[2];
    v18[2] = String[4];
    v5 = sub_401000((int)v18, strlen(v18));
    if ( String[0] == v7[0] + 34
      && String[1] == v10
      && 4 * String[2] - 141 == 3 * v8
      && String[3] / 4 == 2 * (v13 / 9)
      && !strcmp(v4, "ak1w")
      && !strcmp(v5, "V1Ax") )
    {
      MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);
    }
  }
  return 0;
}

解法也算简单

v18 = [90,74,83,69,67,97,78,72,51,110,103]
v18.sort()
from base64 import b64decode 
v18 = bytes([v18[0]+34, v18[4]] ) + b64decode('V1Axak1w') #01,234567
print(v18)
#UJWP1jMp
#flag{UJWP1jMp}

014_[BJDCTF2020]JustRE

几乎是直接给,把19999和0直接写进去就行了

INT_PTR __stdcall DialogFunc(HWND hWnd, UINT a2, WPARAM a3, LPARAM a4)
{
  CHAR String[100]; // [esp+0h] [ebp-64h] BYREF

  if ( a2 != 272 )
  {
    if ( a2 != 273 )
      return 0;
    if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )
    {
      sprintf(String, &Format, ++dword_4099F0);
      if ( dword_4099F0 == 19999 )
      {
        sprintf(String, " BJD{%d%d2069a45792d233ac}", 19999, 0);
        SetWindowTextA(hWnd, String);
        return 0;
      }
      SetWindowTextA(hWnd, String);
      return 0;
    }
    EndDialog(hWnd, (unsigned __int16)a3);
  }
  return 1;
}

015_findit

onCreate方法

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView((int) R.layout.activity_main);
        final EditText edit = (EditText) findViewById(R.id.widget2);
        final TextView text = (TextView) findViewById(R.id.widget1);
        final char[] a = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};
        final char[] b = {'p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}'};
        ((Button) findViewById(R.id.widget3)).setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                char[] x = new char[17];
                char[] y = new char[38];
                for (int i = 0; i < 17; i++) {
                    if ((a[i] < 'I' && a[i] >= 'A') || (a[i] < 'i' && a[i] >= 'a')) {
                        x[i] = (char) (a[i] + 18);
                    } else if ((a[i] < 'A' || a[i] > 'Z') && (a[i] < 'a' || a[i] > 'z')) {
                        x[i] = a[i];
                    } else {
                        x[i] = (char) (a[i] - 8);
                    }
                }
                if (String.valueOf(x).equals(edit.getText().toString())) {
                    for (int i2 = 0; i2 < 38; i2++) {
                        if ((b[i2] < 'A' || b[i2] > 'Z') && (b[i2] < 'a' || b[i2] > 'z')) {
                            y[i2] = b[i2];
                        } else {
                            y[i2] = (char) (b[i2] + 16);
                            if ((y[i2] > 'Z' && y[i2] < 'a') || y[i2] >= 'z') {
                                y[i2] = (char) (y[i2] - 26);
                            }
                        }
                    }
                    text.setText(String.valueOf(y));
                    return;
                }
                text.setText("答案错了肿么办。。。不给你又不好意思。。。哎呀好纠结啊~~~");
            }
        });
    }

翻译成python

a = ['T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e']
b = ['p', 'v', 'k', 'q', '{', 'm', '1', '6', '4', '6', '7', '5', '2', '6', '2', '0', '3', '3', 'l', '4', 'm', '4', '9', 'l', 'n', 'p', '7', 'p', '9', 'm', 'n', 'k', '2', '8', 'k', '7', '5', '}']
a = ''.join(a).encode()
b = ''.join(b).encode()
x = [0]*17
y = [0]*38
for i,v in enumerate(a):
    if (v < ord('I') and v>= ord('A')) or (v < ord('i') and v>= ord('a')):
        x[i] = v+18
    elif (v < ord('A') or v>= ord('Z')) and (v < ord('a') and v> ord('z')):
        x[i] = v 
    else: 
        x[i] = v -8 
print(bytes(x))

for i,v in enumerate(b):
    if (v < ord('A') or v> ord('Z')) and (v < ord('a') or v> ord('z')):
        y[i] = v 
    else: 
        y[i] = v +16
        if (y[i] > ord('Z') and y[i]< ord('a')) or (y[i] >= ord('z')):
            y[i] = y[i]-26
        
print(bytes(y))
#flag{c164675262033b4c49bdf7f9cda28a75}

016_简单注册器

又一个apk的题,onCreate有算法

   public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView((int) R.layout.activity_main);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().add((int) R.id.container, (Fragment) new PlaceholderFragment()).commit();
        }
        final TextView textview = (TextView) findViewById(R.id.textView1);
        final EditText editview = (EditText) findViewById(R.id.editText1);
        ((Button) findViewById(R.id.button1)).setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                int flag = 1;
                String xx = editview.getText().toString();
                if (!(xx.length() == 32 && xx.charAt(31) == 'a' && xx.charAt(1) == 'b' && (xx.charAt(0) + xx.charAt(2)) - 48 == 56)) {
                    flag = 0;
                }
                if (flag == 1) {
                    char[] x = "dd2940c04462b4dd7c450528835cca15".toCharArray();
                    x[2] = (char) ((x[2] + x[3]) - 50);
                    x[4] = (char) ((x[2] + x[5]) - 48);
                    x[30] = (char) ((x[31] + x[9]) - 48);
                    x[14] = (char) ((x[27] + x[28]) - 97);
                    for (int i = 0; i < 16; i++) {
                        char a = x[31 - i];
                        x[31 - i] = x[i];
                        x[i] = a;
                    }
                    textview.setText("flag{" + String.valueOf(x) + "}");
                    return;
                }
                textview.setText("输入注册码错误");
            }
        });
    }

翻译

x = list(b'dd2940c04462b4dd7c450528835cca15')
x[2] = (x[2]+x[3]-50)
x[4] = (x[2]+x[5]-48)
x[30] = (x[31]+x[9]-48)
x[14] = (x[27]+x[28]-97)
print(b'flag{'+bytes(x)[::-1]+b'}')
#flag{59acc538825054c7de4b26440c0999dd}

017_[GWCTF 2019]pyre

一个pyc程序,网上直接反编译

print 'Welcome to Re World!'
print 'Your input1 is your flag~'
l = len(input1)
for i in range(l):
    num = ((input1[i] + i) % 128 + 128) % 128
    code += num

for i in range(l - 1):
    code[i] = code[i] ^ code[i + 1]

print code
code = [
    '\x1f', ...... ]

逆回

code = [
    '\x1f','\x12','\x1d',  '(', '0', '4', '\x01', '\x06', '\x14', '4', ',', '\x1b', 'U', '?', 'o', '6', '*', ':', '\x01', 'D', ';', '%', '\x13']
code = [ord(i) for i in code]
for i in range(len(code)-2,-1,-1):
    code[i] = code[i]^code[i+1]
print(bytes([(v-i+128)%128 for i,v in enumerate(code) ]))
#GWHT{Just_Re_1s_Ha66y!}
#flag{Just_Re_1s_Ha66y!}

018_[ACTF新生赛2020]easyre

简单的查表

int __cdecl main(int argc, const char **argv, const char **envp)
{
  _BYTE v4[12]; // [esp+12h] [ebp-2Eh] BYREF
  _DWORD v5[3]; // [esp+1Eh] [ebp-22h]
  _BYTE v6[5]; // [esp+2Ah] [ebp-16h] BYREF
  int v7; // [esp+2Fh] [ebp-11h]
  int v8; // [esp+33h] [ebp-Dh]
  int v9; // [esp+37h] [ebp-9h]
  char v10; // [esp+3Bh] [ebp-5h]
  int i; // [esp+3Ch] [ebp-4h]

  __main();
  qmemcpy(v4, "*F'\"N,\"(I?+@", sizeof(v4));
  printf("Please input:");
  scanf("%s", v6);
  if ( v6[0] != 65 || v6[1] != 67 || v6[2] != 84 || v6[3] != 70 || v6[4] != 123 || v10 != 125 )
    return 0;
  v5[0] = v7;
  v5[1] = v8;
  v5[2] = v9;
  for ( i = 0; i <= 11; ++i )
  {
    if ( v4[i] != _data_start__[*((char *)v5 + i) - 1] )
      return 0;
  }
  printf("You are correct!");
  return 0;
}

回查

v4 = b"*F'\"N,\"(I?+@"
code = b'\x7e}|{zyxwvutsrqponmlkjihgfedcba`_^]\[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210/.-,+*)(\'&%$# !"@'
#v4[i] != _data_start__[*((char *)v5 + i) - 1] 
print(bytes([code.index(i)+1 for i in v4]))
#U9X_1S_W6@T?
#flag{U9X_1S_W6@T?}

019_rsa

rsa不放到crypto放到reverse,直接给了一个很小可以分解的分解

from gmpy2 import *
from libnum import s2n,n2s 

n = 86934482296048119190666062003494800588905656017203025617216654058378322103517
p = 285960468890451637935629440372639283459
q = n // p 
e = 65537

phi = (p-1)*(q-1)
d = invert(e, phi )
c = open('flag.enc', 'rb').read()
c = s2n(c)
m = pow(c, d, n )
print(m)
print(n2s(int(m)))
#flag{decrypt_256}

020_[ACTF新生赛2020]rome

一个不太复杂的移位操作

              v1[0] = v7;
              v1[1] = v8;
              v1[2] = v9;
              v1[3] = v10;
              *(_DWORD *)&v12[17] = 0;
              while ( *(int *)&v12[17] <= 15 )
              {
                if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 64 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 90 )
                  *((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 51) % 26 + 65;
                if ( *((char *)v1 + *(_DWORD *)&v12[17]) > 96 && *((char *)v1 + *(_DWORD *)&v12[17]) <= 122 )
                  *((_BYTE *)v1 + *(_DWORD *)&v12[17]) = (*((char *)v1 + *(_DWORD *)&v12[17]) - 79) % 26 + 97;
                ++*(_DWORD *)&v12[17];
              }
              *(_DWORD *)&v12[17] = 0;
              while ( *(int *)&v12[17] <= 15 )
              {
                result = (unsigned __int8)v12[*(_DWORD *)&v12[17]];
                if ( *((_BYTE *)v1 + *(_DWORD *)&v12[17]) != (_BYTE)result )
                  return result;
                ++*(_DWORD *)&v12[17];
              }
              return printf("You are correct!");

爆破

import string 
s = b"Qsw3sj_lz4_Ujw@l"

letter = string.ascii_lowercase + string.ascii_uppercase + string.digits + '_@'
flag = ''
for i in range(16):
    for j in letter:
        if j.isupper():
            v = (ord(j)-51)%26 + 65
        elif j.islower():
            v = (ord(j)-79)%26 + 97
        else:
            v = ord(j) 
        #print(v, j ) 
        if v == s[i]:
            flag += j 
            print(flag)
            break 
#Cae3ar_th4_Gre@t
#flag{Cae3ar_th4_Gre@t}

021_CrackRTF

第一步求6位数据的sha1,这个需要爆破

第二步就复杂了,不过后边有人漏洞,它用这个密钥加密后得到的文件有固定文件头(大多数文件都有固定文件头),这个第二步就不用解了,直接用固定头异或得到

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  DWORD v3; // eax
  DWORD v4; // eax
  char Str[260]; // [esp+4Ch] [ebp-310h] BYREF
  int v7; // [esp+150h] [ebp-20Ch]
  char String1[260]; // [esp+154h] [ebp-208h] BYREF
  char Destination[260]; // [esp+258h] [ebp-104h] BYREF

  memset(Destination, 0, sizeof(Destination));
  memset(String1, 0, sizeof(String1));
  v7 = 0;
  printf("pls input the first passwd(1): ");
  scanf("%s", Destination);
  if ( strlen(Destination) != 6 )
  {
    printf("Must be 6 characters!\n");
    ExitProcess(0);
  }
  v7 = atoi(Destination);
  if ( v7 < 100000 )
    ExitProcess(0);
  strcat(Destination, "@DBApp");
  v3 = strlen(Destination);
  sub_40100A((BYTE *)Destination, v3, String1);
  if ( !_strcmpi(String1, "6E32D0943418C2C33385BC35A1470250DD8923A9") )
  {
    printf("continue...\n\n");
    printf("pls input the first passwd(2): ");
    memset(Str, 0, sizeof(Str));
    scanf("%s", Str);
    if ( strlen(Str) != 6 )
    {
      printf("Must be 6 characters!\n");
      ExitProcess(0);
    }
    strcat(Str, Destination);
    memset(String1, 0, sizeof(String1));
    v4 = strlen(Str);
    sub_401019((BYTE *)Str, v4, String1);
    if ( !_strcmpi("27019e688a4e62a649fd99cadaafdb4e", String1) )
    {
      if ( !(unsigned __int8)sub_40100F(Str) )
      {
        printf("Error!!\n");
        ExitProcess(0);
      }
      printf("bye ~~\n");
    }
  }
  return 0;
}

解码

from hashlib import sha1, md5 
import string 

#https://docs.microsoft.com/zh-cn/windows/win32/seccrypto/alg-id?redirectedfrom=MSDN
#0x8004 sha1
for i in range(100000, 1000000):
    #print(sha1(str(i).encode() +b'@DBApp').hexdigest())
    if sha1(str(i).encode() +b'@DBApp').hexdigest().upper() == "6E32D0943418C2C33385BC35A1470250DD8923A9":
        print(i)
        break 
#123321

#ResourceHacker 程序中的文件资源AAA 与密钥异或后生成 dbapp.rtf文件,rtf文件头固定格式,前6字符得到密钥,输入密钥生成文件
aaa = [0x05, 0x7D, 0x41, 0x15, 0x26, 0x01]
rtf = [0x7b, 0x5c, 0x72, 0x74, 0x66, 0x31]
for i in range(6):
    print(chr(aaa[i]^rtf[i]), end='')
#~!3a@0
#Flag{N0_M0re_Free_Bugs}
#flag{N0_M0re_Free_Bugs}

022_[FlareOn4]login

FlareOn都有固定格式,这题比较特殊是javascript,就一句

                var rotFlag = flag.replace(/[a-zA-Z]/g, function(c){return String.fromCharCode((c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26);});
                if ("PyvragFvqrYbtvafNerRnfl@syner-ba.pbz" == rotFlag) {
                    alert("Correct flag!");
                } else {
                    alert("Incorrect flag, rot again");
                }

解密,没有方便的三元运算符,写得较js长

#(c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26
import string 

a = b'PyvragFvqrYbtvafNerRnfl@syner-ba.pbz' #@syner-ba.pbz
for i,v in enumerate(a):
    if chr(v) in '@-.':
        print(chr(v), end='')
    else:
        for jj in string.ascii_uppercase+string.ascii_lowercase:
            j = ord(jj)
            if j <= ord('Z'):
                k = 90
            else:
                k = 122 
            c = j +13
            if c > k:
                c -=26
            if c == v:
                print(chr(j), end='')
                break 
#ClientSideLoginsAreEasy@flare-on.com
#flag{ClientSideLoginsAreEasy@flare-on.com}

023_[2019红帽杯]easyRE

第1段没啥用,第2段是10次base64编译

__int64 sub_4009C6()
{
  __int64 result; // rax
  int i; // [rsp+Ch] [rbp-114h]
  __int64 v2; // [rsp+10h] [rbp-110h]
  __int64 v3; // [rsp+18h] [rbp-108h]
  __int64 v4; // [rsp+20h] [rbp-100h]
  __int64 v5; // [rsp+28h] [rbp-F8h]
  __int64 v6; // [rsp+30h] [rbp-F0h]
  __int64 v7; // [rsp+38h] [rbp-E8h]
  __int64 v8; // [rsp+40h] [rbp-E0h]
  __int64 v9; // [rsp+48h] [rbp-D8h]
  __int64 v10; // [rsp+50h] [rbp-D0h]
  __int64 v11; // [rsp+58h] [rbp-C8h]
  char v12[13]; // [rsp+60h] [rbp-C0h] BYREF
  char v13[4]; // [rsp+6Dh] [rbp-B3h] BYREF
  char v14[19]; // [rsp+71h] [rbp-AFh] BYREF
  char v15[32]; // [rsp+90h] [rbp-90h] BYREF
  int v16; // [rsp+B0h] [rbp-70h]
  char v17; // [rsp+B4h] [rbp-6Ch]
  char v18[72]; // [rsp+C0h] [rbp-60h] BYREF
  unsigned __int64 v19; // [rsp+108h] [rbp-18h]

  v19 = __readfsqword(0x28u);
  qmemcpy(v12, "Iodl>Qnb(ocy", 12);
  v12[12] = 127;
  qmemcpy(v13, "y.i", 3);
  v13[3] = 127;
  qmemcpy(v14, "d`3w}wek9{iy=~yL@EC", sizeof(v14));
  memset(v15, 0, sizeof(v15));
  v16 = 0;
  v17 = 0;
  readn(0, v15, 0x25uLL);
  v17 = 0;
  if ( strlen(v15) == 36 )
  {
    for ( i = 0; i < (unsigned __int64)strlen(v15); ++i )
    {
      if ( (unsigned __int8)(v15[i] ^ i) != v12[i] )
      {
        result = 4294967294LL;
        goto LABEL_13;
      }
    }
    sub_410CC0("continue!");
    memset(v18, 0, 65);
    readn(0, v18, 0x40uLL);
    v18[39] = 0;
    if ( strlen(v18) == 39 )
    {
      v2 = base64encode(v18);
      v3 = base64encode(v2);
      v4 = base64encode(v3);
      v5 = base64encode(v4);
      v6 = base64encode(v5);
      v7 = base64encode(v6);
      v8 = base64encode(v7);
      v9 = base64encode(v8);
      v10 = base64encode(v9);
      v11 = base64encode(v10);
      if ( !(unsigned int)sub_400360(v11, off_6CC090) )
      {
        sub_410CC0("You found me!!!");
        sub_410CC0("bye bye~");
      }
      result = 0LL;
    }
    else
    {
      result = 4294967293LL;
    }
  }
  else
  {
    result = 0xFFFFFFFFLL;
  }
LABEL_13:
  if ( __readfsqword(0x28u) != v19 )
    sub_444020();
  return result;
}

解回

from base64 import b64decode


a = b"Iodl>Qnb(ocy\x7fy.i\x7fd`3w}wek9{iy=~yL@EC"
print(bytes([i^v for i,v in enumerate(a)]))  #b'Info:The first four chars are `flag`'

from base64 import b64decode
a = 'Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xVmpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWxob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1dsWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1ExWlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGSnJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSllUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnRlRXRXTVZaSFVsUnNVVlZVTURrPQ=='
for i in range(10):
    a = b64decode(a)

print(a) #https://bbs.pediy.com/thread-254172.htm
#flag{Act1ve_Defen5e_Test}

024_[GUET-CTF2019]re

这个人得有多恶心

 if ( 1629056 * *a1 != 166163712 )
    return 0LL;
  if ( 6771600 * a1[1] != 731332800 )
    return 0LL;
  if ( 3682944 * a1[2] != 357245568 )
    return 0LL;
  if ( 10431000 * a1[3] != 1074393000 )
    return 0LL;
  if ( 3977328 * a1[4] != 489211344 )
    return 0LL;
  if ( 5138336 * a1[5] != 518971936 )
    return 0LL;
  if ( 7532250 * a1[7] != 406741500 )
    return 0LL;
  if ( 5551632 * a1[8] != 294236496 )
    return 0LL;
......

然后一个个抄下来

def getc(a, b):
     print(chr(b//a), end='')

getc(1629056,166163712)
getc(6771600,731332800)
getc(3682944,357245568)
getc(10431000,1074393000)
getc(3977328,489211344)
getc(5138336,518971936)
print('?', end='')
getc(7532250,406741500)
getc(5551632,294236496)
getc(3409728,177305856)
getc(13013670,650683500)
getc(6088797,298351053)
getc(7884663,386348487)
getc(8944053,438258597)
getc(5198490, 249527520 )
getc(4544518,445362764)
getc(10115280,981182160)
getc(3645600,174988800)
getc(9667504,493042704)
getc(5364450,257493600)
getc(13464540,767478780)
getc(5488432,312840624)
getc(14479500,1404511500)
getc(6451830,316139670)
getc(6252576,619005024)
getc(7763364,372641472)
getc(7327320,373693320)
getc(8741520,498266640)
getc(8871876,452465676)
getc(4086720,208422720)
getc(9374400,515592000)
getc(5759124,719890500)
#flag{e?65421110ba03099a1c039337}
#flag{e165421110ba03099a1c039337}

025_[WUSTCTF2020]level1

一堆数字的简单运算,分奇偶

  for ( i = 1; i <= 19; ++i )
  {
    if ( (i & 1) != 0 )
      printf("%ld\n", (unsigned int)(ptr[i] << i));
    else
      printf("%ld\n", (unsigned int)(i * ptr[i]));
  }

解码

a = [198,232,816,200,1536,300,6144,984,51200,570,92160,1200,565248,756,1474560,800,6291456,1782,65536000]
for i in range(1,20):
    if i&1 != 0:
        print(chr(a[i-1]>>i), end='')
    else:
        print(chr(a[i-1]//i), end='')

#ctf2020{d9-dE6-20c}
#flag{d9-dE6-20c}

026_[SUCTF2019]SignIn

模幂运算,又是rsa

from gmpy2 import invert
from libnum import n2s 

c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
e = 65537
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549

p = 282164587459512124844245113950593348271
q = n//p 
phi = (p-1)*(q-1)
d = invert(e, phi)
m = pow(c,d,n)
print(n2s(int(m)))

#suctf{Pwn_@_hundred_years}
#flag{Pwn_@_hundred_years}

027_[MRCTF2020]Transform

异或运算

  for ( i = 0; i <= 32; ++i )
  {
    byte_414040[i] = Str[dword_40F040[i]];
    byte_414040[i] ^= LOBYTE(dword_40F040[i]);
  }

解码

ae0 = [0x67, 0x79, 0x7B, 0x7F, 0x75, 0x2B, 0x3C, 0x52, 0x53, 0x79, 0x57, 0x5E, 0x5D, 0x42, 0x7B, 0x2D, 0x2A, 0x66, 0x42, 0x7E, 0x4C, 0x57, 0x79, 0x41, 0x6B, 0x7E, 0x65, 0x3C, 0x5C, 0x45, 0x6F, 0x62, 0x4D, 0x3F]
a40 = [9, 0xA, 0x0F, 0x17, 7, 0x18, 0x0C, 0x6, 1, 0x10, 0x3, 0x11, 0x20, 0x1D, 0x0B, 0x1E, 0x1B, 0x16, 4, 0xD, 0x13, 0x14, 0x15, 2, 0x19, 5, 0x1F, 8, 0x12, 0x1A, 0x1C, 0x0E, 0]
print(len(ae0), len(a40))
str = [0]*33
for i in range(33):
    str[a40[i]] = ae0[i]^a40[i] 

print(bytes(str))
#MRCTF{Tr4nsp0sltiON_Clph3r_1s_3z}
#flag{Tr4nsp0sltiON_Clph3r_1s_3z}

028_[WUSTCTF2020]level2

直接给了

mov     [ebp+var_C], offset flag ; "wctf2020{Just_upx_-d}"
sub     esp, 0Ch
push    offset aWhereIsIt ; "where is it?"

029_[ACTF新生赛2020]usualCrypt

变码表的base64

第1变

int sub_401000()
{
  int result; // eax
  char v1; // cl

  for ( result = 6; result < 15; ++result )
  {
    v1 = byte_40E0AA[result];
    byte_40E0AA[result] = byte_40E0A0[result];
    byte_40E0A0[result] = v1;
  }
  return result;
}

第2变

int __cdecl sub_401030(const char *a1)
{
  __int64 v1; // rax
  char v2; // al

  v1 = 0i64;
  if ( strlen(a1) )
  {
    do
    {
      v2 = a1[HIDWORD(v1)];
      if ( v2 < 97 || v2 > 122 )
      {
        if ( v2 < 65 || v2 > 90 )
          goto LABEL_9;
        LOBYTE(v1) = v2 + 32;                   // 大写+32
      }
      else
      {
        LOBYTE(v1) = v2 - 32;                   // 小写-32
      }
      a1[HIDWORD(v1)] = v1;
LABEL_9:
      LODWORD(v1) = 0;
      ++HIDWORD(v1);
    }
    while ( HIDWORD(v1) < strlen(a1) );
  }
  return v1;
}

逆回


a = b'zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9'
pcode = b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

ncode = list(pcode)

for i in range(6,15):
    ncode[i], ncode[i+10] = ncode[i+10], ncode[i]

b = [0]*len(a)

for i,v in enumerate(a):
    if v>=ord('A') and v<=ord('Z'):
        b[i] = v+32
    elif v>=ord('a') and v<=ord('z'):
        b[i] = v-32
    else:
        b[i] = v 
        
    b[i] = pcode[ncode.index(b[i])]
    
from  base64 import b64decode 
print(b64decode(bytes(b)))
#flag{bAse64_h2s_a_Surprise}

030_Youngter-drive

感觉特复杂,先是用两个进程共享一个值,作到仅对奇数位处理

int __cdecl main_0(int argc, const char **argv, const char **envp)
{
  void *v3; // ecx
  HANDLE Thread; // [esp+D0h] [ebp-14h]
  HANDLE hObject; // [esp+DCh] [ebp-8h]

  sub_4110FF(v3);                               // 读flag到Source
  ::hObject = CreateMutexW(0, 0, 0);
  j_strcpy(Destination, Source);
  hObject = CreateThread(0, 0, StartAddress, 0, 0, 0);// 411B10,StartAddress_0交互执行418008 -1,仅单位执行加密处理
  Thread = CreateThread(0, 0, j_ex_418008, 0, 0, 0);// 418008 初始值为29,flag共30字符,最后1位未校验
  CloseHandle(hObject);
  CloseHandle(Thread);
  while ( dword_418008 != -1 )
    ;
  j_check();
  CloseHandle(::hObject);
  return 0;
}

StartAddress里有加密处理

// positive sp value has been detected, the output may be wrong!
char *__cdecl enc(int a1, int a2)
{
  char *result; // eax
  char v3; // [esp+D3h] [ebp-5h]

  v3 = *(_BYTE *)(a2 + a1);
  if ( (v3 < 97 || v3 > 122) && (v3 < 65 || v3 > 90) )
    exit(0);
  if ( v3 < 97 || v3 > 122 )
  {
    result = off_418000[0];
    *(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 38];
  }
  else
  {
    result = off_418000[0];
    *(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 96];
  }
  return result;
}

然后是一个检查

int check()
{
  int i; // [esp+D0h] [ebp-8h]

  for ( i = 0; i < 29; ++i )
  {
    if ( Source[i] != off_418004[i] )
      exit(0);
  }
  return printf("\nflag{%s}\n\n", Destination);
}

看似简单但不对,网上搜了下,问题在这,初始值为0x1d一共30位。但检查运算只有29位。只能爆破提交网站补未位

.data:00418008 1D 00 00 00                   dword_418008 dd 1Dh                

结果

a = b'TOiZiZtOrYaToUwPnToBsOaOapsyS'
b = b'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm '

import string 
for i in range(len(a)):
    if i%2 == 0:
        print(chr(a[i]), end='')
        continue 
    for d in string.ascii_uppercase+string.ascii_lowercase:
        if d>='A' and d<='Z':
            c = b[ord(d)-38]
        else:
            c = b[ord(d)-96]
        if c == a[i]:
            print(d, end='')
            break 
#ThisisthreadofwindowshahaIsES
#flag{ThisisthreadofwindowshahaIsESE}  ?输入30,前面只对比29

得来1分题也不简单,1分题只是因为能搜到wp

031_相册

apk题用jni打开找到这个,解开后得到18218465125@163.com

EXPORT Java_com_net_cn_NativeMethod_m
Java_com_net_cn_NativeMethod_m
; __unwind {
PUSH    {R3,LR}
LDR     R2, [R0]
LDR     R1, =(aMtgymtg0njuxmj_0 - 0xC8E) ; "MTgyMTg0NjUxMjVAMTYzLmNvbQ=="
MOVS    R3, #0x29C
ADD     R1, PC          ; "MTgyMTg0NjUxMjVAMTYzLmNvbQ=="
LDR     R3, [R2,R3]
BLX     R3
POP     {R3,PC}
; End of function Java_com_net_cn_NativeMethod_m

其实这题要的就是email的地址 

flag{18218465125@163.com}

032_[HDCTF2019]Maze

这个一般都是迷宫,找到一个串

.data:00408030 2A 2A 2A 2A 2A 2A 2A 2B 2A 2A+db '*******+********* ******    ****   ******* **F******    **************',0

处理得到

'''
upx去壳
start跳转nop花指令第1字节e8
在main处生成函数
发现是迷宫,横纵坐标78,7c,跟到,发现前面的迷宫,横坐标7,确定是10*7迷宫,折行后得到迷宫,走出线路
*******+**
******* **
****    **
**   *****
** **F****
**    ****
**********
ssaaasaassdddw
'''
#flag{ssaaasaassdddw}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值