【CTF】BUUCTF RE 刷(抄wp)题记录

CTF · 2021-04-01 · 2503 人浏览

:Coolapk140: 本篇可能会持续更新

PART1

RE11:Java逆向解密

这个是为数不多自己做的题

下载来是个.class文件,用jadx打开来是这个样子

看到26有一堆奇奇怪怪的,看着就像ascii的东西,有个加密函数

那么就写个解密脚本

key=[180, 136, 137, 147, 191, 137, 147, 191, 148, 136, 133, 191, 134, 140, 129, 135, 191, 65]
flag=''
for i in key:
    s=(i^32)-ord('@')
    flag+=chr(s)
print flag

运行结果:

flag:flag{This_is_the_flag_!}

RE12:刮开有奖

[hidden]不会,还没写呢[/hidden]

RE13:[GXYCTF2019]luck_guy

21.5.1

又被小端序这个东西坑了:在CTF中的小端序与大端序

下载文件出来

ida64拖进去打开

整个反编译出来逻辑还是比较清楚的,就是switch按照一定顺序执行,就会给flag

看了一下感觉有用的就1,4,5 想了一下可能会是451,4551,45551这几种,然后试了一下试不出来,后面才发现又被小端序这个东西坑到了,然后调整了一下s的顺序

直接把整个关键代码修改一下放进vscode去试一下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"defs.h"

int main(){
  unsigned int v0;
  char v1;
  signed int i;
  signed int j;
  __int64 s;
  char v6;
  unsigned __int64 v7;
  char f1[]={71, 88, 89, 123, 100, 111, 95, 110, 111, 116, 95,0};
  char f2[9];
  int a;

    for ( i = 0; i <= 4; ++i )
    {
        scanf("%d",&a);
        switch ( a  )
        {
          case 1:
            puts("OK, it's flag:");
            memset(&s, 0, 0x28uLL);

            printf("%s %s", f1,f2);
            break;
          case 2:
            printf("Solar not like you");
            break;
          case 3:
            printf("Solar want a girlfriend");
            break;
          case 4:
            v6 = 0;
            f2[7]=127;
            f2[6]=102;
            f2[5]=111;
            f2[4]=96;
            f2[3]=103;
            f2[2]=117;
            f2[1]=99;
            f2[0]=105;
            break;
          case 5:
            for ( j = 0; j <= 7; ++j )
            {
              if ( j % 2 == 1 )
                v1 = f2[j] - 2;
              else
                v1 = f2[j] - 1;
              f2[j] = v1;
            }
            break;
          default:
            puts("emmm,you can't find flag 23333");
            break;
        }
    }
}


输入451就出来了flag

flag:GXY{do_not_hate_me}

RE14:findit

21.5.1

下载下来发现是个apk,直接jadx打开,源码直接出来了

代码都不用写,直接挑出关键代码稍作修改放到vscode里面运行一下就可以了

#include<stdio.h>

int main(){
    char a[] = {'T', 'h', 'i', 's', 'I', 's', 'T', 'h', 'e', 'F', 'l', 'a', 'g', 'H', 'o', 'm', 'e'};
    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', '}'};
    char x[17];
    char y[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] - '\b');
        }
    }


​ 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);
​ }
​ }
​ }
​ for(int i =0;i<17;i++){
​ printf("%c",x[i]);

    }
    printf("\n");
    for(int j=0;j<38;j++){
        printf("%c",y[j]);
    }
}

但是我输出y会乱码,我也不知道为啥

于是就交给手机,把x输进去框框里面,得到flag

flag:flag{c164675262033b4c49bdf7f9cda28a75}

RE15:简单注册器

21.5.8

下载文件,发现是个apk,拖进jadx打开

找到关键代码拖进vscode,稍微做一点修改

#include<stdio.h>

    int main(){
        char x[33] = "dd2940c04462b4dd7c450528835cca15";
            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;
            }
        printf("flag{%s}",x);
    }

运行得到flag

flag:flag{59acc538825054c7de4b26440c0999dd}

RE16:[GWCTF 2019]pyre

21.5.8

下载文件,是一个pyc文件,找某度有个pyc在线反编译

得到源码

#!/usr/bin/env python
# visit http://tool.lu/pyc/ for more information
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',
    '\x12',
    '\x1d',
    '(',
    '0',
    '4',
    '\x01',
    '\x06',
    '\x14',
    '4',
    ',',
    '\x1b',
    'U',
    '?',
    'o',
    '6',
    '*',
    ':',
    '\x01',
    'D',
    ';',
    '%',
    '\x13']

然后根据源码写出解密脚本

code = [
    '\x1f',
    '\x12',
    '\x1d',
    '(',
    '0',
    '4',
    '\x01',
    '\x06',
    '\x14',
    '4',
    ',',
    '\x1b',
    'U',
    '?',
    'o',
    '6',
    '*',
    ':',
    '\x01',
    'D',
    ';',
    '%',
    '\x13']

flag=''

for i in reversed(range(22)):
    code[i]=chr(ord(code[i+1])^ord(code[i]))

for j in range(23):
    flag+=chr(((ord(code[j])-128)%128-j)%128)

print flag

其中有一个地方有点难,就是取余的逆运算([hidden]对于当代痴呆大学生:指我自己[/hidden])
具体可以参考这个:求余逆运算+负数求余

RE17:[BJDCTF2020]JustRE

21.5.9

下载文件,点开看了一下

有个getflag的选项,点一下

弹出一个窗口,点下面click it

会计数,感觉是要动态调试,可惜我不会,于是打开ida,看了一下关键代码

盲猜要点19999下,于是打开ce :Coolapk84:

直接改成19998,最后点一下click it

真不戳

flag:flag{1999902069a45792d233ac}

RE18:rsa

21.5.9

rsa不会,直接抄的BUUCTF RSA

RE21:[2019红帽杯]easyRE

21.5.18

代码好乱,不会,看了一下wp

打开文件,一堆函数,然后shift+f12打开

找到一些东西

看起来就是base64

点进函数

写半天,把这个base64解密了,上面那一串异或了就一个提示

看别人的wp才知道还有个函数在另外一个地方

然后来个脚本

'''a='Iodl>Qnb(ocy'+chr(127)+'y.i'+chr(127)+'d`3w}wek9{iy=~yL@EC'
b=''
for i,j in zip(a,range(len(a))):
    b+=chr(ord(i)^j)
print b'''

v1='flag'
v2=[64,  53,  32,  86,  93,  24,  34,  69,  23,  47, 
   36, 110,  98,  60,  39,  84,  72, 108,  36, 110, 
  114,  60,  50,  69,  91]
key=''
flag=''

for i in range(4):
    key+=chr(v2[i]^ord(v1[i]))

for i in range(len(v2)):
    flag+=chr(v2[i]^ord(key[i%4]))

print flag

flag:flag{Act1ve_Defen5e_Test}

RE22:[ACTF新生赛2020]rome

21.5.18

脚本没写出来 :bili大哭

s='Qsw3sj_lz4_Ujw@l'
flag=''
for i in s:
    if ord(i)>64 and ord(i)<=90:
        flag+=chr((ord(i)-14))
    elif ord(i)>96 and ord(i)<=122:
        flag+=chr((ord(i)-18))
    else:
        flag+=i
print flag

有点问题,不知道为啥,后来就直接抄了cnblog[ BUUCTF--[ACTF新生赛2020]rome][5]

flag:flag{Cae3ar_th4_Gre@t}

RE23:[FlareOn4]login

21.5.26

简单的题

算法都没看,直接试一下alert(rotFlag);

然后随便输入一些字母,发现就是简单的移位

写个脚本

s='PyvragFvqrYbtvafNerRnfl@syner-ba.pbz'
flag=''

for i in s:
    if (i>='a' and i<='m') or (i>='A' and i<='M'):
        flag+=chr(ord(i)+13)
    elif (i>='n' and i<='z') or (i>='N' and i<='Z'):
        flag+=chr(ord(i)-13)
    else:
        flag+=i

print flag

flag:flag{ClientSideLoginsAreEasy@flare-on.com}

RE25:[GUET-CTF2019]re

21.5.26

一堆奇葩东西

手工处理数据之后上脚本

a=[1629056,
6771600,
3682944,
10431000,
3977328,
5138336,
7532250,
5551632,
3409728,
13013670,
6088797,
7884663,
8944053,
5198490,
4544518,
3645600,
10115280,
9667504,
5364450,
13464540,
5488432,
14479500,
6451830,
6252576,
7763364,
7327320,
8741520,
8871876,
4086720,
9374400,
5759124]

b=[166163712,
731332800,
357245568,
1074393000,
489211344,
518971936,
406741500,
294236496,
177305856,
650683500,
298351053,
386348487,
438258597,
249527520,
445362764,
174988800,
981182160,
493042704,
257493600,
767478780,
312840624,
1404511500,
316139670,
619005024,
372641472,
373693320,
498266640,
452465676,
208422720,
515592000,
719890500]


​ flag=''

for i,j in zip(a,b):
    flag+=chr(j/i)
print flag

#坑壁题目缺第七位,看都看不到。。。

坑壁题目缺第七位,看都看不到。。。害我看wp :Coolapk84:

好像要爆破第七位..是1

flag:flag{e165421110ba03099a1c039337}

RE27:相册

21.7.27

时隔多月我又做了一题(主要原因是放假了在玩

首先下载,发现是个apk,那么我们打开jadx看看

这么怪的名字肯定在里面

随便点开几个康康

然后去c2看看

ok,这波属于是写明了是base64了,接下来我们去so文件里面找一下base64的字符

解压得到libcore.so

ida打开,shift+f12

得到几个base64

选中的这个就是flag需要的邮箱了

包上flag提交即可。

flag:flag{18218465125@163.com}

RE29:level1

21.8.3

ida64打开

逻辑很清晰

奇数进行位运算右移,偶数乘以下标

python写个脚本就行了

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

flag:ctf2020{d9-dE6-20c}

RE30:[MRCTF2020]Transform

21.8.5

无壳,打开ida64看一下main

主要的加密还是在这两句

这是数据

具体就是根据索引dword_40F040打乱顺序然后再异或,然后我们只需要反过来即可,也就是倒着循环reversed(range(33))然后先异或再flag[dword_40F040[i]]=byte_40F0E0[i]即可

写出python脚本:

dword_40F040=[0x09,0x0A,0x0F,0x17,0x07,0x18,0x0C,0x06,0x01,0x10,0x03,0x11,0x20,0x1D,0x0B,0x1E,0x1B,0x16,0x04,0x0D,0x13,0x14,0x15,0x02,0x19,0x05,0x1F,0x08,0x12,0x1A,0x1C,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
byte_40F0E0=[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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
flag=[0]*33

for i in reversed(range(0,33)):
    byte_40F0E0[i]^=(dword_40F040[i])
    flag[dword_40F040[i]]=byte_40F0E0[i]
    
print ''.join([chr(x) for x in flag])

flag:flag{Tr4nsp0sltiON_Clph3r_1s_3z}

RE31:[WUSTCTF2020]level2

21.8.5


???
放到kali里面upx -d,shift+f12就出来了

flag:flag{Just_upx_-d}

RE34:[MRCTF2020]Xor

21.10.12

反编译失败,调用函数参数有问题,这里删掉三个点这个东西就行了。

超级简单的异或,直接脚本

a='MSAWB~FXZ:J:`tQJ"N@ bpdd}8g'
flag=''
for i in range(27):
    flag+=chr(i^ord(a[i]))
print flag

flag:MRCTF{@_R3@1ly_E2_R3verse!}

RE35:[FlareOn4]IgniteMe

21.10.14

今天线下打金华市和美杯 来早了,做了个re

ida打开

只有五个函数,

这两个是关键函数,打开看看

这个函数看起来就是对数组初始化,没啥用

这个就比较有用了,可以看到一个简单的异或操作,但是v4初值不知道,点进sub_401000():

查了下这个函数,也没查出什么,动调看看

断点断在那个for循环上面

然后双击v4,可以看到

他的初值是4。

于是写个脚本

a=[   13,  38,  73,  69,  42,  23, 120,  68,  43, 108, 
   93,  94,  69,  18,  47,  23,  43,  68, 111, 110, 
   86,   9,  95,  69,  71, 115,  38,  10,  13,  19, 
   23,  72,  66,   1,  64,  77,  12,   2, 105]
flag=''
b=0
v4=4
for i in reversed(a):
   b=v4^i
   v4=b
   flag+=chr(b)
print flag[::-1]

flag:flag{R_y0u_H0t_3n0ugH_t0_1gn1t3@flare-on.com}

RE36:[MRCTF2020]hello_world_go

21.10.14

go语言 逆向出来是真的复杂啊
完全看不懂

主函数就有flag

flag:flag{hello_world_gogogo}

RE37:[WUSTCTF2020]level3

21.10.19

main函数给了个base64

有个奇怪的换表函数,好像在start的时候被调用了(main之前)

直接动调一下看看被改成啥样了(脚本写了但是好像不太对?

真不戳

然后随便找个换表脚本就出来了

flag:wctf2020{Base64_is_the_start_of_reverse}

RE38:[WUSTCTF2020]Cr0ssfun

21.10.19

手动操作复制出来输出,没什么好说的

flag:wctf2020{cpp_@nd_r3verse_@re_fun}

RE39:[WUSTCTF2020]Cr0ssfun

21.10.19
不太会

参考这个https://blog.csdn.net/weixin_47158947/article/details/107818896

不过md5那个地方X2是变大写,所以这篇文章交不上去,实际flag内需要大写

flag:flag{B8C37E33DEFDE51CF91E}

RE40:[FlareOn6]Overlong

21.10.28

动调改一下就好了1C改成7F

因为字符串很长,而for循环只循环前面28位,改长一点就行了。然后断在start函数的return 0,再点进text复制栈上内容就行了。

flag:flag{I_a_M_t_h_e_e_n_C_o_D_i_n_g@flare-on.com}

RE41:[ACTF新生赛2020]Oruga

21.10.28

打开先验证格式actf{}
然后进到一个函数,看到+16-16+1-1这个,再看到一个奇怪的256字符的数组,直接猜测是迷宫,实际上也确实是的。

这个题比较迷惑,是左上角开始走的,我被迷惑到了,弄成了0是起点,!是终点

而且移动也不是一个一个走,是滑动,题目名字翻译过来也是履带,估计就是想暗示吧。

迷宫走完就行了

象征性的贴个输出迷宫的脚本

map=[0,   0,   0,   0,  35,   0,   0,   0,   0,   0, 
    0,   0,  35,  35,  35,  35,   0,   0,   0,  35, 
   35,   0,   0,   0,  79,  79,   0,   0,   0,   0, 
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
   79,  79,   0,  80,  80,   0,   0,   0,   0,   0, 
    0,  76,   0,  79,  79,   0,  79,  79,   0,  80, 
   80,   0,   0,   0,   0,   0,   0,  76,   0,  79, 
   79,   0,  79,  79,   0,  80,   0,   0,   0,   0, 
    0,   0,  76,  76,   0,  79,  79,   0,   0,   0, 
    0,  80,   0,   0,   0,   0,   0,   0,   0,   0, 
    0,  79,  79,   0,   0,   0,   0,  80,   0,   0, 
    0,   0,  35,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
   35,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
   77,  77,  77,   0,   0,   0,  35,   0,   0,   0, 
    0,   0,   0,   0,   0,   0,   0,  77,  77,  77, 
    0,   0,   0,   0,  69,  69,   0,   0,   0,  48, 
    0,  77,   0,  77,   0,  77,   0,   0,   0,   0, 
   69,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
    0,   0,   0,   0,   0,   0,  69,  69,  84,  84, 
   84,  73,   0,  77,   0,  77,   0,  77,   0,   0, 
    0,   0,  69,   0,   0,  84,   0,  73,   0,  77, 
    0,  77,   0,  77,   0,   0,   0,   0,  69,   0, 
    0,  84,   0,  73,   0,  77,   0,  77,   0,  77, 
   33,   0,   0,   0,  69,  69]
map1=''
for i in range(256):
    if i%16==0:
        map1+='\n'
    if map[i]==0:
        map1+='.'
    map1+=chr(map[i])
print map1

flag:flag{MEWEMEWJMEWJM}

RE42:[FlareOn3]Challenge1

21.10.29

动调复制被初始化的base64表然后拿换标脚本解密就行了。之前写过类似的题

import base64
import string

str1 = "x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q"
'''
a=[0x5A, 0x59, 0x58, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x7A, 0x79, 0x78, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F]
string3=''
for i in a:
    string3+=chr(i)
print(string3)
'''
string1 = "ZYXABCDEFGHIJKLMNOPQRSTUVWzyxabcdefghijklmnopqrstuvw0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

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

flag:flag{sh00ting_phish_in_a_barrel@flare-on.com}

RE43:[UTCTF2020]basic-re

22.1.10

都不想放上来...以后这种太简单的题就不放出来了
直接string或者shift+f12就有的

flag:flag{str1ngs_1s_y0ur_fr13nd}

RE44:[Zer0pts2020]easy strcmp

22.1.10

说实话,这个题挺折腾人的,不过也是因为自己python掌握的不好,类型转换老是搞不明白

不过动调能解决的话就很不错了

拿到题目,上来直接一个strcmp,真的很怪

image-20220111002227465

flag也不是这个东西。边上还有几个奇怪的函数,于是找到了这两个

image-20220111002311582

这个把strcmp的地址改了,为了方便,我重新命名了一下

image-20220111002356328

(忽略那个+=,我改过,原来是-=的)

这个“假的”strcmp就是这么个逻辑,把一坨东西和输入进去的相减,最后得到zer0pts{********CENSORED********}这个东西

那就加回来就行了

python脚本不会类型转换,c语言写也报错,离谱了,于是我直接动调,算是一种新思路吧

image-20220111003039159

这个地方原本是sub的,改成add,然后动调,参数直接写成这样

image-20220111003122202

然后断点在图上那个地方,按几次f4,然后点进去看flag就行了

image-20220111003304328

整个就是属于是一个脑洞题...

flag:flag{l3ts_m4k3_4_DETOUR_t0d4y}

RE45:[ACTF新生赛2020]Universe_final_answer

22.1.11

直接用z3就行了

存个学z3的教程https://firmianay.gitbooks.io/ctf-all-in-one/content/doc/5.8.1_z3.html

image-20220111162001926

打开之后,在这里进入目标函数

image-20220111162211348

一堆公式,丢到python里面用z3求解一下

from z3 import *
solver = Solver()
a1=[BitVec("a1[%d]" % i,16) for i in range(10)]
solver.add(-85 * a1[8] + 58 * a1[7] + 97 * a1[6] + a1[5] + -45 * a1[4] + 84 * a1[3] + 95 * a1[0] - 20 * a1[1] + 12 * a1[2] == 12613)
solver.add(30 * a1[9] + -70 * a1[8] + -122 * a1[6] + -81 * a1[5] + -66 * a1[4] + -115 * a1[3] + -41 * a1[2] + -86 * a1[1] - 15 * a1[0] - 30 * a1[7] == -54400)
solver.add(-103 * a1[9] + 120 * a1[7] + 108 * a1[5] + 48 * a1[3] + -89 * a1[2] + 78 * a1[1] - 41 * a1[0] + 31 * a1[4] - (a1[6] << 6) - 120 * a1[8] == -10283)
solver.add(71 * a1[6] + (a1[5] << 7) + 99 * a1[4] + -111 * a1[2] + 85 * a1[1] + 79 * a1[0] - 30 * a1[3] - 119 * a1[7] + 48 * a1[8] - 16 * a1[9] == 22855)
solver.add(5 * a1[9] + 23 * a1[8] + 122 * a1[7] + -19 * a1[6] + 99 * a1[5] + -117 * a1[4] + -69 * a1[2] + 22 * a1[1] - 98 * a1[0] + 10 * a1[3] == -2944)
solver.add(-54 * a1[9] + -23 * a1[7] + -82 * a1[2] + -85 * a1[0] + 124 * a1[1] - 11 * a1[3] - 8 * a1[4] - 60 * a1[5] + 95 * a1[6] + 100 * a1[8] == -2222)
solver.add(-83 * a1[9] + -111 * a1[5] + -57 * a1[0] + 41 * a1[1] + 73 * a1[2] - 18 * a1[3] + 26 * a1[4] + 16 * a1[6] + 77 * a1[7] - 63 * a1[8] == -13258)
solver.add(81 * a1[9] + -48 * a1[8] + 66 * a1[7] + -104 * a1[6] + -121 * a1[5] + 95 * a1[4] + 85 * a1[3] + 60 * a1[2] + -85 * a1[0] + 80 * a1[1] == -1559)
solver.add(101 * a1[9] + -85 * a1[8] + 7 * a1[6] + 117 * a1[5] + -83 * a1[4] + -101 * a1[3] + 90 * a1[2] + -28 * a1[1] + 18 * a1[0] - a1[7] == 6308)
solver.add(99 * a1[9] + -28 * a1[8] + 5 * a1[7] + 93 * a1[6] + -18 * a1[5] + -127 * a1[4] + 6 * a1[3] + -9 * a1[2] + -93 * a1[1] + 58 * a1[0] == -1697)
if solver.check() == sat:
    m = solver.model()
flag1=''
for i in [str(m.eval(a1[i])) for i in range(10)]:
    if int(i)>32768:
        i=int(i)-32768
    flag1+=chr(int(i))
print flag1

然后解出来的东西再放到题目里面运行一下就可以出来flag

flag:flag{F0uRTy_7w@_42}

PART 2

接下来可能不会继续做一分题了(除非找信心)

[MRCTF2020]Shit

题目给出了源码,甚至给了decode函数。不确定的就是key,在启动后会修改。于是使用ollydbg动调出key

源码:

#include<Windows.h>
#include<iostream>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int map[100],c=2;
int key[7]={'b','k','d','c','e','w'};
unsigned int ks[6]={0x8c2c133a,0xf74cb3f6,0xfedfa6f2,0xab293e3b,0x26cf8a2a,0x88a1f279};//{0x8c2cecc5,0xf74cb3f6,0xfedf590d,0xab293e3b,0x26cf75d5,0x88a1f279};
FARPROC proc=NULL;
int initHook()
{
    HMODULE hModule=LoadLibraryA("Kernel32.dll");
    if(hModule)
    {
        proc=GetProcAddress(hModule,"IsDebuggerPresent");
        if(proc==NULL)
            return -1;
    }
    return 0;
}
PDWORD update()
{
    if(initHook()!=0)
        exit(-1);
    HANDLE hProcess=GetModuleHandle(NULL);
    PIMAGE_DOS_HEADER dos_header=(PIMAGE_DOS_HEADER)hProcess;
    PIMAGE_NT_HEADERS nt_header=(PIMAGE_NT_HEADERS)(dos_header->e_lfanew+(DWORD)hProcess);
    IMAGE_OPTIONAL_HEADER* opt_header=&(nt_header->OptionalHeader);
    PIMAGE_IMPORT_DESCRIPTOR iat=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hProcess+opt_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    while(iat->FirstThunk)
    {
        PIMAGE_THUNK_DATA data=(PIMAGE_THUNK_DATA)(iat->FirstThunk+(DWORD)hProcess);
        while(data->u1.Function)
        {
            if(IMAGE_SNAP_BY_ORDINAL(data->u1.AddressOfData))
            {
                data++;
                continue;
            }
            if((DWORD)proc==data->u1.Function)
                return &data->u1.Function;
            data++;
        }
        iat++;
    }
    return NULL;
}
PDWORD table_addr=NULL;
int writeAddr(DWORD addr)
{
    if(table_addr==NULL)
        table_addr=update();
    DWORD dwOldProtect;
    MEMORY_BASIC_INFORMATION mbi_thunk;
    VirtualQuery(table_addr,&mbi_thunk,sizeof(MEMORY_BASIC_INFORMATION));
    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,PAGE_READWRITE,&mbi_thunk.Protect);
    *table_addr=(DWORD)addr;
    VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,mbi_thunk.Protect,&dwOldProtect);
    return 0;
}
bool WINAPI CallBackProc()
{
    writeAddr((DWORD)proc);
    map[0]=2;c--;
    key[0]='a';
    key[1]='k';
    key[2]='e';
    key[3]='y';
    key[4]='e';
    key[5]='z';
    if(IsDebuggerPresent())
    {
        MessageBoxW(NULL,L"U R Using Debugger!",L"U Suck!",MB_OK);
        return true;
    }
    return false;
}
void sleep()
{
    sleep();
}
int checkDebug()
{
    if(*((unsigned char *)(*(DWORD*)(__readfsdword(0x18)+0x30))+0x2))
        sleep();
    return 0;
}
int doit=writeAddr((DWORD)CallBackProc),dd=checkDebug();
bool encode(char* ur_flag)
{
    unsigned int k=0,bk=0;   
    for(int i=0;i<strlen(ur_flag);i+=4)
    {
        k=(((int)ur_flag[i])<<24)|(((int)ur_flag[i+1])<<16)|(((int)ur_flag[i+2])<<8)|((int)ur_flag[i+3]);
        k=(k>>key[i/4]) | (k<<(32-key[i/4]));
        _asm
        {
            call sub2
            _emit 0xEB
            jmp label2
        sub2:
            add dword ptr[esp],1
            retn
        label2:
        }
        k=((~(k>>16))&0x0000ffff) | (k<<16);
        k=(1<<key[i/4])^k;
        _asm
        {
            call sub7
            _emit 0xE8
            jmp label7
        sub7:
            add dword ptr[esp],1
            retn
        label7:
        }
        if(i>0)
            k^=bk;
        bk=k;
        if(k!=ks[i/4])
            return false;
    }
    return true;
}
void genKey()
{
    int len=20,keylen=6,maxium=0;
    int before;
    _asm
    {
        call sub1
        _emit 0xE8
        jmp label1
    sub1:
        add dword ptr[esp],1
        retn
    label1:
    }
    srand(time(NULL));
    for(int i=1;i<=len;i++)
    {
        map[i]=map[i-1]+rand()%5;
        _asm
        {
            call sub3
            _emit 0xE8
            jmp label3
        sub3:
            add dword ptr[esp],1
            retn
        label3:
        }
        maxium=maxium>map[i]?maxium:map[i];
    }
    _asm
    {
        call sub4
        _emit 0xE8
        jmp label4
    sub4:
        add dword ptr[esp],1
        retn
    label4:
    }
    before=time(NULL);
    _asm
    {
        call sub5
        _emit 0xE8
        jmp label5
    sub5:
        add dword ptr[esp],1
        retn
    label5:
    }
    for(int i=0;i<keylen;i++)
    {
        int step=0;
        long long t=time(NULL);
        int delta=t-before;
        _asm
        {
            call sub6
            _emit 0xE8
            jmp label6
        sub6:
            add dword ptr[esp],1
            retn
        label6:
        }
        if(delta>maxium)
            return;
    
        for(int j=0;j<=len;j++)
            if(delta<=map[j])
            {
                step=map[j];
                _asm
                {
                    call sub8
                    _emit 0xE8
                    jmp label8
                sub8:
                    add dword ptr[esp],1
                    retn
                label8:
                }
                break;
            }
        _asm
        {
            call sub9
            _emit 0xE8
            jmp label9
        sub9:
            add dword ptr[esp],1
            retn
        label9:
        }
        key[i]=(key[i]*c+step+i*3)%32;
        _asm
        {
            call sub10
            _emit 0xE8
            jmp label10
        sub10:
            add dword ptr[esp],1
            retn
        label10:
        }
        before=t;
    }
}

void decode()
{
    unsigned int k=0,bk=0;
    for(int i=5;i>=0;i--)
        if(i>0)
            ks[i]^=ks[i-1];
    for(int i=0;i<24;i+=4)
    {
        k=ks[i/4];
        k=(1<<key[i/4])^k;
        k=((k>>16)) | ((~(k<<16))&0xffff0000);
        k=((k<<key[i/4])) | (k>>(32-key[i/4]));
        printf("%X\n",k);
    }
}
int main()
{
    char ur_flag[50];
    cout<<"please input your flag:"<<endl;
    cin>>ur_flag;
    if(IsDebuggerPresent())
    {
        cout<<"U suck! 233333"<<endl;
        Sleep(2000);
        exit(0);
    }
    if(strlen(ur_flag)!=24)
    {
        cout<<"Wrong!"<<endl;
        Sleep(2000);
        exit(0);
    }
    genKey();
    bool flag=encode(ur_flag);
    decode();
    if(flag)
    {
        cout<<"U did it!"<<endl<<"GJ!"<<endl;
        system("pause");
        exit(0);
    }
    cout<<"Wrong!"<<endl;
    Sleep(2000);
    return 0;
}

里面还有一些新的花指令,学到了

前面还有时间差反调试,学到许多,直接把time函数nop掉然后把0移进去就好了,其实按f9按得快一点也可以出

image-20220208184500437

在ida nop掉花指令之后(或者直接od nop掉也可以,但是ida有插件快一点)我们用od断在这里,先随便输24位数字,然后看ecx一个一个提取出来就可以了

image-20220208162025593

注意od好像不会自动识别代码,需要按ctrl+a重新识别再动调。

最后取出来keykey[7] = { 0x03,0x10,0x0D,0x04,0x13,0x0B }

直接拿源代码改一下就可以了

#include<Windows.h>
#include<iostream>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int map[100], c = 2;
//int key[7] = { 'a','k','e','y','e','z' };
int key[7] = { 0x03,0x10,0x0D,0x04,0x13,0x0B };
unsigned int ks[6] = { 0x8c2c133a,0xf74cb3f6,0xfedfa6f2,0xab293e3b,0x26cf8a2a,0x88a1f279 };//{0x8c2cecc5,0xf74cb3f6,0xfedf590d,0xab293e3b,0x26cf75d5,0x88a1f279};
FARPROC proc = NULL;
void decode()
{
    unsigned int k = 0, bk = 0;
    for (int i = 5; i >= 0; i--)
        if (i > 0)
            ks[i] ^= ks[i - 1];
    for (int i = 0; i < 24; i += 4)
    {
        k = ks[i / 4];
        k = (1 << key[i / 4]) ^ k;
        k = ((k >> 16)) | ((~(k << 16)) & 0xffff0000);
        k = ((k << key[i / 4])) | (k >> (32 - key[i / 4]));
        //printf("%X\n", k);
        for (int j = 0; j < 4; j++) {
            printf("%c", *((char*)&k + 3 - j));
        }
    }
}
int main()
{
    char ur_flag[50];
    cout << "please input your flag:" << endl;
    //genKey();
    //bool flag=encode(ur_flag);
    decode();
    /*if(flag)
    {
        cout<<"U did it!"<<endl<<"GJ!"<<endl;
        system("pause");
        exit(0);
    }
    cout<<"Wrong!"<<endl;
    Sleep(2000);*/
    system("pause");
    return 0;
}

flag:flag{a_3a2y_re_for_test}

[watevrCTF 2019]Repyc

题目给了一个pyc文件,在线反编译一下,原本有很多佤 = 0 侰 = ~佤 * ~佤 俴 = 侰 + 侰 def 䯂(䵦):这种东西,用vscode自带的匹配所有,改一下全部改成人看的字符。本来改完就有点想放弃了,直接搜了下wp,发现是一个vm,第一次接触这种题目。还挺有意思的。自己整理了一下做了一遍

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
a = 0
b = ~a * ~a  #1
c = b + b  #2


def func(x):
    f1 = 0
    f3 = [a] * 16
    f4 = [a] * 100
    f5 = []
    while x[f1][a] != "exit":
        k1 = x[f1][a].lower()
        k2 = x[f1][b:]
        if k1 == "add":
            f3[k2[a]] = f3[k2[b]] + f3[k2[c]]
        elif k1 == "xor":
            f3[k2[a]] = f3[k2[b]] ^ f3[k2[c]]
        elif k1 == "sub":
            f3[k2[a]] = f3[k2[b]] - f3[k2[c]]
        elif k1 == "x":
            f3[k2[a]] = f3[k2[b]] * f3[k2[c]]
        elif k1 == "/":
            f3[k2[a]] = f3[k2[b]] / f3[k2[c]]
        elif k1 == "&":
            f3[k2[a]] = f3[k2[b]] & f3[k2[c]]
        elif k1 == "|":
            f3[k2[a]] = f3[k2[b]] | f3[k2[c]]
        elif k1 == "nop":
            f3[k2[a]] = f3[k2[a]]
        elif k1 == "mov":
            f3[k2[a]] = f3[k2[b]]
        elif k1 == "mov1":
            f3[k2[a]] = k2[b]
        elif k1 == "mov2":
            f4[k2[a]] = f3[k2[b]]
        elif k1 == "mov3":
            f3[k2[a]] = f4[k2[b]]
        elif k1 == "to0":
            f3[k2[a]] = a
        elif k1 == "to_0":
            f4[k2[a]] = a
        elif k1 == "input":
            f3[k2[a]] = input(f3[k2[b]])
        elif k1 == "input1":
            f4[k2[a]] = input(f3[k2[b]])
        elif k1 == "print":
            print(f3[k2[a]])
        elif k1 == "print1":
            print(f4[k2[a]])
        elif k1 == "\xeb\xad\xbf":
            f1 = f3[k2[a]]
        elif k1 == "\xeb\xae\x93":
            f1 = f4[k2[a]]
        elif k1 == "\xeb\xae\xb3":
            f1 = f5.pop()
        elif k1 == "\xeb\xaf\x83" or f3[k2[b]] > f3[k2[c]]:
            f1 = k2[a]
            f5.append(f1)
            continue
        elif k1 == "for_comp?":
            f3[7] = a
            for i in range(len(f3[k2[a]])):
                if f3[k2[a]] != f3[k2[b]]:
                    f3[7] = b
                    f1 = f3[k2[c]]
                    f5.append(f1)
        elif k1 == "for_xor":
            m = ""
            for i in range(len(f3[k2[a]])):
                m += chr(ord(f3[k2[a]][i]) ^ f3[k2[b]])
            f3[k2[a]] = m
        elif k1 == "for_-":
            m = ""
            for i in range(len(f3[k2[a]])):
                m += chr(ord(f3[k2[a]][i]) - f3[k2[b]])
            f3[k2[a]] = m
        elif k1 == "\xeb\x96\x87" or f3[k2[b]] > f3[k2[c]]:
            f1 = f3[k2[a]]
            f5.append(f1)
            continue
        elif k1 == "\xeb\x97\x8b" or f3[k2[b]] > f3[k2[c]]:
            f1 = f4[k2[a]]
            f5.append(f1)
            continue
        elif k1 == "\xeb\x98\xb7" or f3[k2[b]] == f3[k2[c]]:
            f1 = k2[a]
            f5.append(f1)
            continue
        elif k1 == "\xeb\x9a\xab" or f3[k2[b]] == f3[k2[c]]:
            f1 = f3[k2[a]]
            f5.append(f1)
            continue
        elif k1 == "\xeb\x9d\x87" and f3[k2[b]] == f3[k2[c]]:
            f1 = f4[k2[a]]
            f5.append(f1)
            continue
        f1 += b


func(
    [
        ["mov1", 0, "Authentication token: "],
        ["input1", 0, 0],
        [
            "mov1",
            6,
            "\xc3\xa1\xc3\x97\xc3\xa4\xc3\x93\xc3\xa2\xc3\xa6\xc3\xad\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\x9b\xc3\xa3\xc3\xa5\xc3\xa4\xc3\x89\xc3\x96\xc3\x93\xc3\x89\xc3\xa4\xc3\xa0\xc3\x93\xc3\x89\xc3\x96\xc3\x93\xc3\xa5\xc3\xa4\xc3\x89\xc3\x93\xc3\x9a\xc3\x95\xc3\xa6\xc3\xaf\xc3\xa8\xc3\xa4\xc3\x9f\xc3\x99\xc3\x9a\xc3\x89\xc3\x9b\xc3\x93\xc3\xa4\xc3\xa0\xc3\x99\xc3\x94\xc3\x89\xc3\x93\xc3\xa2\xc3\xa6\xc3\x89\xc3\xa0\xc3\x93\xc3\x9a\xc3\x95\xc3\x93\xc3\x92\xc3\x99\xc3\xa6\xc3\xa4\xc3\xa0\xc3\x89\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\x9f\xc3\xa5\xc3\x89\xc3\xa4\xc3\xa0\xc3\x93\xc3\x89\xc3\x9a\xc3\x93\xc3\xa1\xc3\x89\xc2\xb7\xc3\x94\xc3\xa2\xc3\x97\xc3\x9a\xc3\x95\xc3\x93\xc3\x94\xc3\x89\xc2\xb3\xc3\x9a\xc3\x95\xc3\xa6\xc3\xaf\xc3\xa8\xc3\xa4\xc3\x9f\xc3\x99\xc3\x9a\xc3\x89\xc3\x85\xc3\xa4\xc3\x97\xc3\x9a\xc3\x94\xc3\x97\xc3\xa6\xc3\x94\xc3\x89\xc3\x97\xc3\x9a\xc3\xaf\xc3\xa1\xc3\x97\xc3\xaf\xc3\xa5\xc3\x89\xc3\x9f\xc3\x89\xc3\x94\xc3\x99\xc3\x9a\xc3\xa4\xc3\x89\xc3\xa6\xc3\x93\xc3\x97\xc3\x9c\xc3\x9c\xc3\xaf\xc3\x89\xc3\xa0\xc3\x97\xc3\xa2\xc3\x93\xc3\x89\xc3\x97\xc3\x89\xc3\x91\xc3\x99\xc3\x99\xc3\x94\xc3\x89\xc3\xa2\xc3\x9f\xc3\x94\xc3\x89\xc3\x96\xc3\xa3\xc3\xa4\xc3\x89\xc3\x9f\xc3\x89\xc3\xa6\xc3\x93\xc3\x97\xc3\x9c\xc3\x9c\xc3\xaf\xc3\x89\xc3\x93\xc3\x9a\xc3\x9e\xc3\x99\xc3\xaf\xc3\x89\xc3\xa4\xc3\xa0\xc3\x9f\xc3\xa5\xc3\x89\xc3\xa5\xc3\x99\xc3\x9a\xc3\x91\xc3\x89\xc3\x9f\xc3\x89\xc3\xa0\xc3\x99\xc3\xa8\xc3\x93\xc3\x89\xc3\xaf\xc3\x99\xc3\xa3\xc3\x89\xc3\xa1\xc3\x9f\xc3\x9c\xc3\x9c\xc3\x89\xc3\x93\xc3\x9a\xc3\x9e\xc3\x99\xc3\xaf\xc3\x89\xc3\x9f\xc3\xa4\xc3\x89\xc3\x97\xc3\xa5\xc3\xa1\xc3\x93\xc3\x9c\xc3\x9c\xc2\x97\xc3\x89\xc3\xaf\xc3\x99\xc3\xa3\xc3\xa4\xc3\xa3\xc3\x96\xc3\x93\xc2\x9a\xc3\x95\xc3\x99\xc3\x9b\xc2\x99\xc3\xa1\xc3\x97\xc3\xa4\xc3\x95\xc3\xa0\xc2\xa9\xc3\xa2\xc2\xab\xc2\xb3\xc2\xa3\xc3\xaf\xc2\xb2\xc3\x95\xc3\x94\xc3\x88\xc2\xb7\xc2\xb1\xc3\xa2\xc2\xa8\xc3\xab",
        ],
        ["mov1", 2, 120],
        ["mov1", 4, 15],
        ["mov1", 3, 1],
        ["x", 2, 2, 3],
        ["add", 2, 2, 4],
        ["nop", 0, 2],
        ["to0", 3],
        ["for_xor", 6, 3],
        ["mov1", 0, "Thanks."],
        ["mov1", 1, "Authorizing access..."],
        ["print", 0],
        ["mov3", 0, 0],
        ["for_xor", 0, 2],
        ["for_-", 0, 4],
        ["mov1", 5, 19],
        ["for_comp?", 0, 6, 5],
        ["print", 1],
        ["exit"],
        ["mov1", 1, "Access denied!"],
        ["print", 1],
        ["exit"],
    ]
)

有两个寄存器f3和f4,只要一个一个把注释搞出来就挺清楚的了。先读进去一个input放在f4的0位上面,然后把key读进去放在f3的6上面,先让key和0异或(迷惑行为),再让input和135异或,再减15。

key="á×äÓâæíäàßåÉÛãåäÉÖÓÉäàÓÉÖÓåäÉÓÚÕæïèäßÙÚÉÛÓäàÙÔÉÓâæÉàÓÚÕÓÒÙæäàÉäàßåÉßåÉäàÓÉÚÓáÉ·Ôâ×ÚÕÓÔɳÚÕæïèäßÙÚÉÅä×ÚÔ×æÔÉ×Úïá×ïåÉßÉÔÙÚäÉæÓ×ÜÜïÉà×âÓÉ×ÉÑÙÙÔÉâßÔÉÖãäÉßÉæÓ×ÜÜïÉÓÚÞÙïÉäàßåÉåÙÚÑÉßÉàÙèÓÉïÙãÉáßÜÜÉÓÚÞÙïÉßäÉ×åáÓÜÜ\x97ÉïÙãäãÖÓ\x9aÕÙÛ\x99á×äÕà©â«³£ï²ÕÔÈ·±â¨ë"
flag=''
for i in range(len(key)):
    flag+=chr((ord(key[i])+15)^135)
print(flag)

脚本有坑,编码的问题,弄成之前/x的格式出不来,而且必须python3解,不清楚为什么。

flag长得离谱,还有个404网站链接

flag:flag{this_must_be_the_best_encryption_method_evr_henceforth_this_is_the_new_Advanced_Encryption_Standard_anyways_i_dont_really_have_a_good_vid_but_i_really_enjoy_this_song_i_hope_you_will_enjoy_it_aswell!_youtube.com/watch?v=E5yFcdPAGv0}

[CFI-CTF 2018]powerPacked

拿到手看了下,发现里面有packed by upx的字样,直接upx脱壳

然后ida反编译不能f5

掏出ghrida,确实还是挺好使的

image-20220409145548539

一个巨简单的加减

a=[0x45,0x48,0x4b,0x7d,0x6b,0x61,0x6e,0x71,0x78,0x67,0x61,0x72,0x71,0x79,0x67,0x74,0x72,0x65]
flag=""
for i in a:
    flag+=chr(i-2)
print flag

image-20220409145755018

flag:flag{i_love_powerpc}

CTF RE
Theme Jasmine by Kent Liao