1

0.s1gn1n

image

最后那一段是程序的判断

异或可以这样看(虽然还是有一点抽象)

1 2 3 4 5 6 7
  1^2          6^7 
1 2` 3` 4`

异或解密:

#include <windows.h>
#include <stdio.h>

int main() {
	int a[] = {0x58,0x69,0x7B,0x6,0x1E,0x38,0x2C,0x20,0x4,0xF,0x1,0x7,0x31,0x6B,0x8,0xE,0x7A,0xA,0x72,0x72,0x26,0x37,0x6F,0x49,0x21,0x16,0x11,0x2F,0x1A,0xD,0x3C,0x1F,0x2B,0x32,0x1A,0x34,0x37,0x7F,0x3,0x44,0x16,0xE,0x1,0x28,0x1E,0x68,0x64,0x23,0x17,0x9,0x3D,0x64,0x6A,0x69,0x63,0x18,0x18,0xA,0x15,0x70};
	char flag[60];
	flag[0] = 0x58;
	for(int i = 1 ;i<60;i++){
		flag[i] = a[i] ^ flag[i-1];
	}
	printf("%s",flag);
    return 0;
}//X1JLRjFfbmlkZ197MG5GaV9pQGVycnRMfTNzM21ucmlDZ2VubkV2X1RJRXM=

image

中序的问题可以用映射来解决,动调可以发现变换的规律

image

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr得到了fPgHhQiDjRkIlSmBnToJpUqErVKWAXLYFZMaCbNcGdOe(44位是flag的长度)

#include <stdio.h>
#include <string.h>

int main() {
	char flag[44] = {0};
	const char enc[] = "_RKF1_nidg_{0nFi_i@errtL}3s3mnriCgennEv_TIEs";
	const char s1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr";
	const char s2[] = "fPgHhQiDjRkIlSmBnToJpUqErVKWAXLYFZMaCbNcGdOe";
	
	int map[128] = {0};
	for (int i = 0; i < 44; i++) {
		map[s2[i]] = i;
	}
	
	for (int i = 0; i < 44; i++) {
		char m = s1[i];
		int index = map[m];
		flag[i] = enc[index];
	}
	
	printf("%s", flag);
	return 0;
}

flag:miniLCTF{esrevER_gnir33nignE_Is_K1nd_0F_@rt}

x96re

retf跳转到这里,异或0x4c

image

image

image

image

image

最后两位没有异或所以两段拼接一下

miniLCTF{3ac159d665b4ccfb25c0927c1a23edb3}

[NewStarCTF 2023 公开赛道]SMC

偶然找到的一道题,和我之前做的简单的异或类型的smc不一样

image

shellcode和smc都会像这样更改权限,所以要留意这这个地址

其他的大佬博客也很清晰了

https://blog.csdn.net/2401_84404094/article/details/148739478

image

image

可能是修改了一次程序的原因,在没修改的时候更加明显,命名为ipaddress

image

将这里undefine再强制转换为code,这样就还原了加密函数(ida的类型识别感觉总有点问题)

image

#include <windows.h>
#include <stdio.h>

int main() {
	int flag[] = {0x7C,0x82,0x75,0x7B,0x6F,0x47,0x61,0x57,0x53,0x25,0x47,0x53,0x25,0x84,0x6A,0x27,0x68,0x27,0x67,0x6A,0x7D,0x84,0x7B,0x35,0x35,0x48,0x25,0x7B,0x7E,0x6A,0x33,0x71};
	for(int i = 0 ;i<32;i++){
		flag[i] = (flag[i]-5)^0x11;
		printf("%c",flag[i]);
	}
    return 0;
}

flag:flag{SMC_1S_1nt3r3sting!!R1ght?}

CS1.6

以前遇到的C#都是unity游戏的类型,这是第一次看到编译成exe的

这里用ilspy比dnspy好用

运行之后出现提示

image

搜索'失败'

image

拿到密文之后CyberChef竟然可以直接出

image

Ez_asm

感觉magic_flag2函数有点奇怪

magic_flag1 是异或0x17

magic_flag3 是加索引

magic_flag2 有一个判断,if (flag[i] == 36 + i) flag[i] += i

在逆向的时候我觉得应该是if(36+i==a[i]-i)这样判断的,但这样不行

验证了一下

加密逻辑:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
	char flag[] = "NSSCTF{ASM_In_Rev3rs3_i3_e333z333}";
	for(int i=0;i<36;i++){
		flag[i] ^= 0x17;
		if(36+i==flag[i]) flag[i]+=i;
		flag[i]+=i;
		printf("%d,",flag[i]);
	}
}//89,69,70,87,71,86,114,93,76,99,82,105,-123,85,83,-127,113,53,119,119,56,93,-108,59,96,-117,62,63,64,-118,66,67,68,-117,57,8

解密逻辑:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
	int a[] = {89,69,70,87,71,86,114,93,76,99,82,105,133,85,83,129,113,70,119,119,76,93,148,82,96,139,88,90,92,138,96,98,100,139,34};
	for(int i=0;i<36;i++){
		a[i]-=i;
		int m = 36+i;
		if(a[i]==m) a[i]-=i;
		printf("%c",(a[i])^0x17);
	}
}//NSSCTF{ASM_In_Rev3rs3_i3_e333z333}

所以说确实题目有点问题

攻防世界-mfc逆向

在这里用spy++来查找控件,xspy来分析

MFC 控件是封装了 Windows UI 元素的类,简化了界面开发流程。

窗口句柄(HWND):唯一标识符

mfc1

mfc2

image

看到这里的类像是密文

用xspy分析

image

这一个是自定义消息

向这个窗口发送自定义消息(借助win32api)

#include<stdio.h>
#include<string.h>
#include "windows.h"

int main()
{
	HWND h = FindWindowA("944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b",NULL);
		//FindWindowA(窗口类名,窗口标题)获取窗口句柄,NULL表示忽略标题
	//窗口类名是“944c8d100f82f0c18b682f63e4dbaa207a2f1e72581c2f1b”,窗口标题是“Flag就在控件里”
	if (h)
	{
		SendMessage(h, 0x464, NULL, NULL);
		//SendMessage(目标窗口句柄,消息id,wParam ,lParam)
		//wParam 传递 简单数据(如标志位、数值、句柄等)
		//lParam 传递 复杂数据(如指针、结构体地址、字符串等)
	}
	getchar();//防止控制台立即关闭,方便观察输出或调试
	return 0;
}

运行之后,出现了des加密的key

image

根据des-ecb加密方式,key为8位

image

xuans

image

根据这里可以判定是sm4加密

image

在main函数里面,sm4加密前有shellcode,这是在对key进行加密

image

shellcode放进ida看出是异或

异或得到真正的key

#include<stdio.h>
int main(){
	int a[]={0x39,0x5A,0x3B,0x5D,0x3C,0xA,0x3E,0x8,0x3E,0x5F,0x6F,0x5D,0x65,0x7,0x61,0x3};
	int len=sizeof(a)/sizeof(a[0]);
	int b[len];
	for(int i=len-1;i>0;i--){
		a[i]=a[i]^a[i-1];
	}
	for(int i=0;i<sizeof(a)/sizeof(a[0]);i++){
		printf("0x%x,",a[i]);
	}
}
//0x39,0x63,0x61,0x66,0x61,0x36,0x34,0x36,0x36,0x61,0x30,0x32,0x38,0x62,0x66,0x62

但是解出fakeflag

image

真正的密文大概两种方法找到,一是手翻函数,二是动调方式追踪到替换函数(没有复现成功)

找到sub_4019A5函数

image

z3求解

from z3 import *

s = Solver()  # 创建了一个 Solver 对象 s
a1 = [BitVec('a%d' % i,16) for i in range(32)]  # 变量

s.add(118 * a1[2] + 173 * a1[0] + 48 * a1[1] + 193 * a1[3] == 66131)
s.add(196 * a1[1] + 68 * a1[0] + 104 * a1[2] + 10 * a1[3] == 52620)
s.add(88 * a1[2] + 22 * a1[0] + 37 * a1[1] + 71 * a1[3] == 36011)
s.add(59 * a1[2] + 141 * a1[1] + 89 * a1[0] + 194 * a1[3] == 61842)
s.add(175 * a1[6] + 88 * a1[5] + 40 * a1[4] + 89 * a1[7] == 65258)
s.add(26 * a1[6] + 166 * a1[5] + 82 * a1[4] + 78 * a1[7] == 58176)
s.add(149 * a1[6] + 73 * a1[4] + 10 * a1[5] + 116 * a1[7] == 62478)
s.add(176 * a1[6] + 198 * a1[4] + 80 * a1[5] + 193 * a1[7] == 114069)
s.add(178 * a1[10] + 100 * a1[9] + 83 * a1[8] + 30 * a1[11] == 56170)
s.add(143 * a1[10] + 148 * (a1[8] + a1[9]) + 168 * a1[11] == 70647)
s.add(33 * a1[8] + 194 * a1[9] + 10 * a1[10] + 186 * a1[11] == 53174)
s.add(32 * a1[10] + (a1[8] << 7) + 33 * a1[9] + 152 * a1[11] == 26118)
s.add(184 * a1[14] + 115 * a1[13] + 164 * a1[12] + 29 * a1[15] == 81254)
s.add(129 * a1[13] + 35 * a1[12] + 129 * a1[14] + 165 * a1[15] == 78646)
s.add(134 * a1[13] + 54 * a1[12] + 39 * a1[14] + 18 * a1[15] == 29827)
s.add(106 * a1[14] + 133 * a1[13] + 80 * a1[12] + 43 * a1[15] == 53660)
s.add(121 * a1[18] + 187 * a1[16] + 32 * a1[17] + 2 * a1[19] == 24667)
s.add(170 * a1[17] + 66 * a1[16] + 58 * a1[18] + 36 * a1[19] == 44188)
s.add(103 * a1[16] + 120 * a1[17] + 12 * a1[18] + 175 * a1[19] == 52310)
s.add(83 * a1[16] + 92 * a1[17] + 129 * a1[18] + 143 * a1[19] == 46020)
s.add(141 * a1[22] + 54 * a1[21] + 100 * a1[20] + 122 * a1[23] == 66732)
s.add(85 * a1[21] + 171 * a1[20] + 69 * a1[22] + 7 * a1[23] == 46817)
s.add((a1[22] << 7) + 197 * a1[20] + 48 * a1[21] + 132 * a1[23] == 83536)
s.add(181 * a1[21] + 101 * a1[20] + 79 * a1[22] + 144 * a1[23] == 80587)
s.add(149 * a1[24] + 187 * a1[25] + 24 * a1[26] + 142 * a1[27] == 92687)
s.add(49 * a1[26] + 86 * a1[25] + 118 * a1[24] + 50 * a1[27] == 49285)
s.add(164 * a1[26] + 170 * a1[25] + 70 * a1[24] + 193 * a1[27] == 92711)
s.add(95 * a1[26] + 198 * a1[25] + 96 * a1[24] + a1[27] == 61904)
s.add(114 * a1[28] + 179 * a1[29] + 37 * a1[30] + 163 * a1[31] == 53864)
s.add(132 * a1[30] + 94 * a1[29] + 49 * a1[28] + 99 * a1[31] == 36980)
s.add(150 * a1[30] + 113 * a1[29] + 43 * a1[28] + (a1[31] << 7) == 40829)
s.add(115 * a1[30] + 139 * a1[29] + a1[28] + 44 * a1[31] == 22448)


if s.check() == sat: #检查当前添加的所有约束条件是否存在满足的解,sat为满足
    m = s.model()
    # 按顺序打印所有变量的值
    result = [m[a1[i]].as_long() % 0xff for i in range(32)]
    print(','.join([hex(x) for x in result]))
#0x1d,0x7f,0xea,0x8e,0x9b,0x89,0x91,0xf3,0x50,0xe6,0x91,0x18,0xd7,0x32,0xb3,0xfc,0x49,0xc1,0x26,0x79,0xa8,0x71,0x62,0xf6,0xa1,0xd4,0x2d,0xc5,0xe4,0x3b,0x59,0x56

因为有移位操作,所以用BitVec,并且是16位二进制

image

posted @ 2025-07-07 11:36  zzz222666  阅读(22)  评论(0)    收藏  举报