栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

2021-10-04 CTF-Reserve

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2021-10-04 CTF-Reserve

文章目录
  • 基础框架
    • 指令体系
    • 逆向分析
    • 算法识别
    • 反调试
      • Windows
        • 自动化反调试
      • Linux
      • 虚拟机保护
    • 脚本语言逆向
  • RxEncode
    • 分析
  • Real_easy_python
    • 分析
    • EXP
  • Protection
    • 分析
    • EXP
  • SimpleRe
    • 分析
  • Thank you Javascript
    • 分析
  • EasyCPP
    • 分析
    • EXP
  • AlgorithmTask-HardTask
    • 分析
  • EasyShell
    • 分析
  • [MRCTF2020]Xor
    • 分析
    • EXP
  • [GWCTF 2019]xxor
    • 分析
    • EXP
  • [ACTF新生赛2020]usualCrypt
    • 分析
    • EXP

基础框架 指令体系 逆向分析 算法识别

通常CTF中会出现base64、TEA、AES、RC4、MD5等算法

特征:

算法
base6464+1位表、右移左移取二进制操作
TEA每轮加密涉及移位 <<4 >>5 与 delta常量(0x9e3779b9)
AES主要特征为sbox(0x63)和逆sbox(0x52)
RC4涉及初始化函数和加密函数(交换s[i]与s[j])、 %256
MD5散列常量:0x67452301、0xefcdab89、0x98badcfe、0x10325476
反调试 Windows 自动化反调试

当遇到花指令或其他需要Patch汇编时

  1. 使用IDAPatch
  2. 使用IDCPython自动化批量Patch
Linux 虚拟机保护

通常,VMProtect等商用软件采用了虚拟机保护技术,它们核心都会有一个vm_init阶段完成初始化自己的一套(ISA)指令集架构

脚本语言逆向

.NET/Python/Java

RxEncode 分析

静态分析 很像是换表的base64
关键算法:

C 库函数 **char strrchr(const char str, int c) 在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。

已经确定是换表的basee64解码,等待进一步完善RXEncode.py的EXP

Real_easy_python 分析

查壳是 python3.7的pyc文件

使用uncompyle6工具解码转换py:
root@ubuntu:~# uncompyle6 -o puzzle.py puzzle.pyc

解码代码:

# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.5.2 (default, Jan 26 2021, 13:30:48) 
# [GCC 5.4.0 20160609]
# Embedded file name: ./source.py
# Compiled at: 2020-08-03 05:55:47
# Size of source mod 2**32: 515 bytes
key = [
 115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35]
print('Input your flag: ', end='')
flag = input()
out = []
for i in flag:
    out.append(ord(i) >> 4 ^ ord(i))

if len(out) != len(key):
    print('TRY AGAIN!')
    exit()
for i in range(len(out)):
    if out[i] != key[i]:
        print('TRY AGAIN!')
        exit()

print('you are right! the flag is : moectf{%s}' % flag)
EXP

顺加倒解

key = [
 115, 76, 50, 116, 90, 50, 116, 90, 115, 110, 48, 47, 87, 48, 103, 50, 106, 126, 90, 48, 103, 116, 126, 90, 85, 126, 115, 110, 105, 104, 35]
for i in range(len(key)):
    out.append(chr(key[i] >>4  ^ key[i]))

print(''.join(out))#moectf{tH1s_1s_th3-R3a1ly_3asy_Python!}
Protection 分析

查壳UPX3.96

脱壳后,发现是xor,照葫芦还原x^y=flag

快速转换数组(convert)

丝滑~moectf{upx_1S_simp1e-t0_u3e}

EXP
x=[0x61, 0x6F, 0x75, 0x76, 0x23, 0x40, 0x21, 0x56, 0x30, 0x38, 0x61, 0x73, 0x64, 0x6F, 0x7A, 0x70, 0x6E, 0x6D, 0x61, 0x26, 0x2A, 0x23, 0x25, 0x21, 0x24, 0x5E, 0x26, 0x2A, 0x00]
y=[0x0C, 0x00, 0x10, 0x15, 0x57, 0x26, 0x5A, 0x23, 0x40, 0x40, 0x3E, 0x42, 0x37, 0x30, 0x09, 0x19, 0x03, 0x1D, 0x50, 0x43, 0x07, 0x57, 0x15, 0x7E, 0x51, 0x6D, 0x43, 0x57, 0x00, 0x00, 0x00, 0x00]

ans=''
for i in range(len(x)):
    ans+=chr(x[i]^y[i])

print(ans)
SimpleRe 分析

MOE2020

简单的XOR,在动态中解密

顺加逆解,xor一遍是加密,xor第二遍就是解密
满足公式:

a^b=c 
c^a=b 
a^b^c=0

Thank you Javascript 分析

去在线解混淆JS代码
http://edit.89tool.com/

const io = require('console-read-write');
async
function main() {
    io.write('MoeCTF 2020 ThankYouJavascript --written by Reverier');
    io.write(await io.read());
    io.write(`Hello $ {
        await io.ask('Who are you?')
    } ! `);
    let saidHi = false;
    while (!saidHi) {
        io.write('Please input the true flag:');
        saidHi = await io.read() === 'moectf{Fx' + 'c' + 'k_' + 'Y' + '0' + 'u-' + 'Jav' + 'aS' + 'cr' + 'ipt' + '!}'
    }
    io.write('Congratulations! You find the flag!')
}
main();

得到flag:moectf{Fxck_Y0u-Javascript!}

EasyCPP 分析

nop

继续分析发现是一个简单的变换算法,其余的都是混淆:

笔记

  1. unknown lib name
  2. 对于调试保护可以用Patch修改
EXP
import binascii


def encode(old):
#old="YWFhYQ=="
    ans=""
    for i in range(len(old)):
        i=old[i]
        num=ord(i)
        if(i.islower()):
            ans+=chr((num+3-97)%26+97)
        elif i.isupper():
            ans+=chr((num+3-65)%26+65)
        else:ans+=chr(num)


def decode(old):
    #old="BZIkBT=="#YWFhYQ=="
    ans=""
    for i in range(len(old)):
        i=old[i]
        num=ord(i)
        if(i.islower()):
            anx=(num-97)%26 +97-3
            if(anx<97):
                anx=97+26-(97-anx)
            
            ans+=chr(anx)
            print((num-97)%26 +97-3)

        elif i.isupper():
            anx=(num-65)%26 +65-3
            if(anx<65):
                anx=65+26-(65-anx)
            
            ans+=chr(anx)
            print((num-65)%26 +65-3)
        else:ans+=chr(num)
    return ans

print(decode("eZ9oB3Uph0QTXI9FBYQIQmUiT2IoX0EbAcIWA3PzA2YkBZIkf3o9"))
print(chr((89+3-65)%26+65))


AlgorithmTask-HardTask 分析

MOE2019

strncmp

若str1与str2的前n个字符相同,则返回0;

程序流程被混淆,稍微分析了下、将字符串用a转换了一下,重新反编译恢复字符串:

case 1750495256: // 第一段flag关键算法

一共分2段flag

  1. dcba3261b6ef0d77(16位)
  2. X1I0X0YxYWdfWTB1XzRyZV9TdHIwbmd9

第二段base64可以解出来:_R4_F1ag_Y0u_4re_Str0ng}
看了WP,盲猜是MD5算法,在cmd5查询是enj0y

要大胆猜RE,就那几种算法,不用想太复杂~

flag:moectf{enj0y_R4_F1ag_Y0u_4re_Str0ng}

EasyShell 分析

MOE2019 RE

DIE查询是UPX3.94

使用UPX Shell脱壳

[MRCTF2020]Xor 分析

这个似乎会阻止伪代码转换

很明显,在动态调试算法在这:

在动态调试中,发现算法是还原xor真实密码,并且逐个比较
还原公式=(变形flag ^ 字符索引)

笔记:

  1. 未转换的变量为字符串,再按A重新转换(第一个字符)
EXP
oldstr=[0x4D, 0x53, 0x41, 0x57, 0x42, 0x7E, 0x46, 0x58, 0x5A, 0x3A, 0x4A, 0x3A, 0x60, 0x74, 0x51, 0x4A, 0x22, 0x4E, 0x40, 0x20, 0x62, 0x70, 0x64, 0x64, 0x7D, 0x38,0x67]

ans=''
for i in range(len(oldstr)):
    ans+=chr(oldstr[i]^i)

print(ans)
[GWCTF 2019]xxor 分析

是一道算法题 (类似于TEA)

先解方程,通过z3求解:

主要验证代码:

主要算法代码:(类似TEA轮加密)

在数组中,伪代码

*input = input[0]

看了WP提示

a2[1]
a2[2]取值,要看类型
_DWORD 占4位

*a2=a2+0*4=a2
a2[1]= a2 +1*4



在动态调试中观察,可以很明显发现

其实是取

    byte_601078 = v6[j];
    unk_60107C = v6[j+1];       

注意的点:

  1. unsigned 符号类型 变量类型很重要
  2. 加密顺,解密倒着完事
EXP
void __fastcall decalc()
{
	 __int64 xorm[6];
	xorm[0] = 3746099070;
	xorm[1] = 550153460;
	xorm[2] = 3774025685;
	xorm[3] = 1548802262;
	xorm[4] = 2652626477;
	xorm[5] = 2230518816;
	unsigned int  i = 0, j = 0, sum;
	unsigned int  temp[2] = { 0 };
	unsigned int  data[4] = { 2,2,3,4 };//unk哪个数字
	for (i = 0; i < 5; i += 2)
	{
		temp[0] = xorm[i];
		temp[1] = xorm[i + 1];

		sum = 0x458BCD42 * 64;//类似于tea 逆向
		for (j = 0; j < 64; j++)
		{
			temp[1] -= (temp[0] + sum + 20) ^ ((temp[0] << 6) + 3) ^ ((temp[0] >> 9) + 4) ^ 0x10;
			temp[0] -= (temp[1] + sum + 11) ^ ((temp[1] << 6) + 2) ^ ((temp[1] >> 9) + 2) ^ 0x20;
			sum -= 0x458BCD42;
		}
		xorm[i] = temp[0];
		xorm[i + 1] = temp[1];
	}
	for (i = 0; i < 6; i++)
		printf("%c%c%c", *((char*)&xorm[i] + 2), *((char*)&xorm[i] + 1), *(char*)&xorm[i]);

}
int main()
{
	decalc();


}
[ACTF新生赛2020]usualCrypt 分析

经典的base64

动态调试后换表:
ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/

继续分析,发现base64后还有一个大小写颠倒的算法函数:

EXP
import string
from pwn import *
oldtable="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
newtable="ABCDEFQRSTUVWXYPGHIJKLMNOZabcdefghijklmnopqrstuvwxyz0123456789+/"

dictA={}
for i in range(len(oldtable)):
    dictA[newtable[i]]=oldtable[i]

dictA["="]="="

convert_data="zMXHz3TIgnxLxJhFAdtZn2fFk3lYCrtPC2l9"

ans=""
for i in range(len(convert_data)):
    now=ord(convert_data[i])
    if(now<97 or now>122):# no ||  is or
        if((now<65 or now>90)==False):
            now=now+32
    else:
        now=now-32
    

    ans=ans+dictA[chr(now)]

print(b64d(ans))
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/293646.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号