Loading

2021美团安洵暗泉re部分复现

安洵杯

sign_in

贪吃蛇 虽然没啥用 smc解密拿一下flag相关的部分

image-20211229154821395

倒着看看sub_40105F 和sub_401055函数

image-20211229155052896

写出解密算法后发现v5不太对 所以爆破一下v5 反回去看到v5是byte赋值来的

#include <iostream>
#include <stdio.h>
#include <string>
#include <windows.h>
using namespace std;
#include <ctime>
#include <stdlib.h>
#include <windows.h>
unsigned char Enc[] = { 0xA5, 0xD8, 0x8E, 0xBF, 0xF9, 0xA9, 0x15, 0xE1, 0x8A,
0xF0,
0xD3, 0xFC, 0x46, 0x89, 0xBF, 0x8B, 0x62, 0xB1, 0x08, 0xC3,
0x29, 0xCF, 0x19, 0x2B, 0x56, 0x06, 0x77, 0x7A, 0xBA, 0xE4,
0xBA, 0xA4, 0xE4, 0x8C, 0x3E, 0x4E, 0xD9, 0xE1, 0xA7, 0x01,
0x04, 0xCE, 0xE9, 0x75, 0xB9, 0x93, 0xB5, 0x22, 0xB4, 0x42,
0x77, 0x49, 0xF6, 0x15, 0xEB, 0x24, 0x0E, 0xFF, 0xC2, 0xF2,
0x39, 0x30, 0x97, 0x47, 0x0D, 0xCA, 0x01, 0xC8, 0x61, 0x58,
0x12, 0x6A, 0xE8, 0x0B, 0x32, 0x80, 0x47, 0xBD, 0x85, 0x03,
0xDD, 0x6D, 0xF9, 0x69, 0xD1, 0x90, 0x64, 0xE5, 0x4B, 0xAD,
0x3C, 0x2D, 0xBE, 0x00, 0x42, 0x2D, 0x79, 0x69, 0xEF, 0x89,
0x5D, 0x88, 0x91, 0x4A, 0xC7, 0xEB, 0x9D, 0x01, 0x96, 0xFD,
0xF8, 0x3B, 0x57, 0x25, 0xDD, 0x1B, 0xDD, 0x5F, 0x68, 0xB8,
0x14, 0x66, 0x22, 0x57, 0x28, 0x5C, 0x58, 0x9F };
DWORD a2[] = { 68,48,103,51 };
DWORD key[] = { 68,48,103,51 };
DWORD get_v8(int times, int x) {
	DWORD v5 = 'D3g0' + x;
	DWORD v8 = 0;
	for (int i = 0; i < times; i++) {
		v8 += v5;
	}
	return v8;
}
void my_TEAdecode() {
	uint32_t a1[32] = { 0 };
	for (int x = 0; x < 256; x++) {
		x = 77;
		memcpy(a1, Enc, 128);
		for (int v7 = 7; v7 > 0; v7--) {
			DWORD v8 = get_v8(v7, x);
			DWORD v6 = (v8 >> 2) & 3;
			DWORD v9 = a1[30];
			a1[31] -= ((v9 ^ (a2[v6 ^ 31 & 3])) + (*a1 ^ v8)) ^ (((16 * v9)
				^ (*a1 >> 3))
				+ ((4 * *a1) ^ (v9 >> 5)));
			for (int i = 30; i >= 0; i--) {
				if (i == 0) {
					v9 = a1[31];
					a1[i] -= ((v9 ^ a2[v6 ^ i & 3]) + (a1[i + 1] ^ v8)) ^ (((16 * v9) ^ (a1[i + 1] >> 3))
						+ ((4 * a1[i + 1]) ^ (v9 >> 5)));
				}
				else {
					v9 = a1[i - 1];
					a1[i] -= ((v9 ^ a2[v6 ^ i & 3]) + (a1[i + 1] ^ v8)) ^ (((16 * v9) ^ (a1[i + 1] >> 3))
						+ ((4 * a1[i + 1]) ^ (v9 >> 5)));
				}
			}
		}
		//bytes 赋值来的 所以肯定小于256
		if (a1[0] < 256) {
			printf("%d,%d\n", x, a1[0]);
			break;
		}
	}
	for (int i = 0; i < 32; i++) {
		printf("%d,", a1[i]);
	}
}
int main() {
	my_TEAdecode();
	//解得ENC为
	char ENC[] = { 60,64,43,102,111,79,92,29,66,26,43,87,54,68,51,28,29,107,92,6,15,28,92,26,43,9,50,110,21,90,44,37, };

}

然后一步步解密即可

# tea解密出来得
enc = [60, 64, 43, 102, 111, 79, 92, 29, 66, 26, 43, 87, 54, 68, 51, 28, 29, 107, 92, 6, 15, 28, 92, 26, 43, 9, 50, 110,
       21, 90, 44, 37]
know = [0xA5, 0xD8, 0x8E, 0xBF, 0xF9, 0xA9, 0x15, 0xE1, 0x8A, 0xF0,
        0xD3, 0xFC, 0x46, 0x89, 0xBF, 0x8B, 0x62, 0xB1, 0x08, 0xC3,
        0x29, 0xCF, 0x19, 0x2B, 0x56, 0x06, 0x77, 0x7A, 0xBA, 0xE4,
        0xBA, 0xA4, 0xE4, 0x8C, 0x3E, 0x4E, 0xD9, 0xE1, 0xA7, 0x01,
        0x04, 0xCE, 0xE9, 0x75, 0xB9, 0x93, 0xB5, 0x22, 0xB4, 0x42,
        0x77, 0x49, 0xF6, 0x15, 0xEB, 0x24, 0x0E, 0xFF, 0xC2, 0xF2,
        0x39, 0x30, 0x97, 0x47, 0x0D, 0xCA, 0x01, 0xC8, 0x61, 0x58,
        0x12, 0x6A, 0xE8, 0x0B, 0x32, 0x80, 0x47, 0xBD, 0x85, 0x03,
        0xDD, 0x6D, 0xF9, 0x69, 0xD1, 0x90, 0x64, 0xE5, 0x4B, 0xAD,
        0x3C, 0x2D, 0xBE, 0x00, 0x42, 0x2D, 0x79, 0x69, 0xEF, 0x89,
        0x5D, 0x88, 0x91, 0x4A, 0xC7, 0xEB, 0x9D, 0x01, 0x96, 0xFD,
        0xF8, 0x3B, 0x57, 0x25, 0xDD, 0x1B, 0xDD, 0x5F, 0x68, 0xB8,
        0x14, 0x66, 0x22, 0x57, 0x28, 0x5C, 0x58, 0x9F]
kk = []
v1 = [0] * 300
j = 0
i = 0
v7 = 0
table = [0] * 32
#原先函数的逻辑就是将输入值打乱 所以现在看看打乱顺序是什么
v6 = [x for x in range(1, 33)]
while (i < 32):
    if (j % 6 >= 3):
        v1[32 * (3 - j % 3) + i] = v6[i]
    else:
        v1[32 * (j % 3) + i] = v6[i]
    i += 1
    j += 1
for i in range(4):
    for j in range(32):
        if (v1[32 * i + j]):
            table[v7] = v1[32 * i + j]
            v7 += 1

for index in range(len(enc)):
    table[index] -= 1
sb = [0] * 32
for index in range(32):
    sb[table[index]] = enc[index]
sb[31] ^= sb[0]
for i in range(31, 0, -1):
    sb[i - 1] ^= sb[i % 32]
sb = "".join(list(map(chr, sb)))
print(sb)

maze

并没有算出迷宫解法 这个迷宫怎么走也走不对 所以抄了别人的迷宫答案复现下面的部分

base64换表密码很简单 上脚本什么的都行 解出来一半flag

最后的异或逻辑什么的也能看懂 虽然我并不知道为什么要异或...

DNUICTF

sign_in

打开就是flag

happyctf

拿到字符串梭了 不想看逻辑

a="rxusoCqxw{yqK`{KZqag{r`i"
b=list(map(ord,list(a)))
print(b)
for i in range(100):
    print()
    for index in range(len(a)):
        print(chr(ord(a[index])^i),end="")

rc4

x = [0xE8, 0x9B, 0x41, 0x28, 0xCC, 0x7F, 0xDF, 0x20, 0x2C, 0x54,
     0x6E, 0x5F, 0xBE, 0x0E, 0xA4, 0x7B, 0xCF, 0x46, 0xED, 0x71,
     0xE8, 0x46, 0x7E, 0x7D, 0x00, 0xA3, 0x0B, 0x40]
p = []
# 穿了一堆2进去 然后动调拿到x
for c in x:
    p.append(c ^ ord("2"))
print(p)



enc = [0x9E, 0xE7, 0x30, 0x5F, 0xA7, 0x01, 0xA6, 0x53, 0x59, 0x1B,
       0x0A, 0x20, 0xF1, 0x73, 0xD1, 0x0E, 0xAB, 0x09, 0x84, 0x0E,
       0x8D, 0x2B, ]
ENC = []
for x in enc:
    ENC.append(x ^ 0x22)
print(ENC)
# p现在是密钥
for index in range(len(ENC)):
    print(chr(p[index] ^ ENC[index]), end="")

easyre

直到现在我也没动态调出来 但是gdb操作学了一堆...

然后看了加密与解密的二十章二十一章

现在勉强能看懂别的师傅的注册机写法

https://mp.weixin.qq.com/s/KgxHOFH52EE8z7NnMTSIDA 别的师傅的wp

本题是通过用linux的信号来触发各个函数 相当于写了个虚拟机 所以我们有两种思路 一是分析一下每个函数的作用 二是动态调试直接看结果是怎么变化的

先拿到他都发送了什么信号

[17, 52, 0, 42, 5, 16, 20, 9, 23, 0, 36, 5, 3, 17, 29, 6, 0, 0, 5, 3, 17, 64, 6, 0, 72, 5, 17, 29, 23, 14, 1, 21, 4, 15, 1, 22, 2, 0, 0, 4, 3, 5, 16, 20, 50, 5, 9, 2, 19, 29, 5, 18, 21, 4, 16, 20, 61, 10, 1, 19, 52, 3, 4, 18, 14, 1, 21, 4, 7, 1, 22, 2, 0, 0, 4, 3, 5, 16, 20, 85, 5, 9, 1, 19, 64, 5, 18]

在init里面有一堆信号处理函数 一个个分析对应 理解一下都是干什么的....

抄了一份脚本慢慢分析

opcode=[17, 52, 0, 42, 5, 16, 20, 9, 23, 0, 36, 5, 3, 17, 29, 6, 0, 0, 5, 3, 17, 64, 6, 0, 72, 5, 17, 29, 23, 14, 1, 21, 4, 15, 1, 22, 2, 0, 0, 4, 3, 5, 16, 20, 50, 5, 9, 2, 19, 29, 5, 18, 21, 4, 16, 20, 61, 10, 1, 19, 52, 3, 4, 18, 14, 1, 21, 4, 7, 1, 22, 2, 0, 0, 4, 3, 5, 16, 20, 85, 5, 9, 1, 19, 64, 5, 18]
data=[0]*512
cnt=0
target=0
def sig_hand(sig:int,a1=None):
   global cnt
   s='unknown:{}'.format(sig)
   if sig==34:
       # data[esp++]=a1
       s='push {}'.format(a1)
   elif sig==35:
       s='pop {}'.format(a1)
   elif sig==36:
       s='add rax,rbx'
   elif sig==37:
       s='add {},{}'.format(a1,target)
   elif sig==38:
       s='sub rax,rbx'
   elif sig==39:
       s='sub {},{}'.format(a1,target)
   elif sig==40:
       s='xor rax,rbx'
   elif sig==41:
       s='test rax,rbx' # set flag
   elif sig==42:
       s='call {}'.format(target)
   elif sig==43:
       s='ret'
   elif sig==44:
       s='jmp {}'.format(target)
   elif sig==45:
       s='jz {}'.format(target)
   elif sig==46:
       s='push data[rcx]'
   elif sig==47:
       s='pop data[rcx]'
   elif sig==2:
       s='check'
   return s
ip_lst=[0,8,9,10,12,13,14,17,19,20]
while cnt<len(opcode):
   op=opcode[cnt]
   s='unknown'
   last_cnt=cnt
   cnt+=1
   if op in ip_lst:
       target=opcode[cnt]
       cnt+=1
   if op==0:
       s=sig_hand(34,target)
   elif op==1:
       s=sig_hand(34,'rax')
   elif op==2:
       s=sig_hand(34,'rbx')
   elif op==3:
       s=sig_hand(34,'rcx')
       pass
   elif op==4:
       s=sig_hand(35,'rax')
   elif op==5:
       s=sig_hand(35,'rbx')
   elif op==6:
       s=sig_hand(35,'rcx')
   elif op==7:
       s=sig_hand(36)
   elif op==8:
       s=sig_hand(37,'rax')
   elif op==9:
       s=sig_hand(37,'rbx')
   elif op==10:
       s=sig_hand(37,'rcx')
   elif op==11:
       s=sig_hand(38)
       pass
   elif op==12:
       s=sig_hand(39,'rax')
   elif op==13:
       s=sig_hand(39,'rbx')
   elif op==14:
       s=sig_hand(39,'rcx')
   elif op==15:
       s=sig_hand(40)
   elif op==16:
       s=sig_hand(41)
   elif op==17:
       s=sig_hand(42)
   elif op==18:
       s=sig_hand(43)
   elif op==19:
       s=sig_hand(44)
   elif op==20:
       s=sig_hand(45)
   elif op==21:
       s=sig_hand(46)
   elif op==22:
       s=sig_hand(47)
   else:
       s=sig_hand(2)
   print("%02d:%s"%(last_cnt,s))

拿到汇编结果后就很简单了 就是简单的异或和加减运算 直接写解密脚本


enc = [0xA3, 0xD8, 0xAC, 0xA9, 0xA8, 0xD6, 0xA6, 0xCD, 0xD0, 0xD5,
       0xF7, 0xB7, 0x9C, 0xB3, 0x31, 0x2D, 0x40, 0x5B, 0x4B, 0x3A,
       0xFD, 0x57, 0x42, 0x5F, 0x58, 0x52, 0x54, 0x1B, 0x0C, 0x78,
       0x39, 0x2D, 0xD9, 0x3D, 0x35, 0x1F, 0x09, 0x41, 0x40, 0x47,
       0x42, 0x11]

p = []
for index in range(len(enc)):
    p.append(((enc[index] ^ (0x9a - index * 2)) - 41 + index) ^ (0x76 - index * 2))
for x in p:
    print(chr(x), end="")

美团

random

多输入几个值会发现 这个random其实是定值 直接传一串a进去 动态拿到异或后结果

a = [  0x39, 0xC0, 0xAA, 0x88, 0x8C, 0x4D, 0x8D, 0x9A, 0x88, 0xA5,
  0x77, 0xF6, 0xF8, 0xD0, 0xC5, 0x88, 0xA2, 0xA7, 0xE1, 0xDE,
  0x5F, 0x25, 0x79, 0x4F, 0x12, 0x37, 0x33, 0xD9, 0x3A, 0x07,
  0x8C, 0xDD, 0xEB, 0xB9, 0x57, 0xEE, 0x87, 0xB2, 0xD0, 0x30,
  0xD8, 0x38]
b = [0x3E, 0xCD, 0xAA, 0x8E, 0x96, 0x1F, 0x89, 0xCD, 0xDB, 0xF1,
     0x70, 0xF2, 0xA9, 0x9C, 0xC2, 0x8B, 0xF2, 0xFE, 0xAD, 0x8B,
     0x58, 0x7C, 0x2F, 0x03, 0x4A, 0x65, 0x31, 0x89, 0x76, 0x57,
     0x88, 0xDF, 0xB8, 0xE9, 0x01, 0xE9a, 0xDE, 0xE5, 0x86, 0x68,
     0x8F, 0x24, 0xD3, 0x5A]
print('a'*42)
print(chr(0x61))
for index in range(len(a)):
    print(chr(a[index] ^ 0x61 ^ b[index]), end="")

wow

萌新大受震撼 是32位程序运行64位代码

https://zhuanlan.zhihu.com/p/57648345

根据文章内容

在x64系统下的进程是有32位和64位两种工作模式,这两种工作模式的区别在于CS寄存器。32位模式时,CS = 0x23;64位模式时,CS = 0x33。;

这两种工作模式是可以进行切换的,一般会通过retf指令,一条retf指令等效于以下2条汇编指令

pop ip
pop cs

如果此时栈中有0x33,则会将0x33弹出到CS寄存器中,实现32位程序切换到64位代码的过程。所以retf是识别32位程序调用64位代码的重要标志。

image-20211229162147239

很明显的切换标志 所以我们把下面的代码dump出来 用ida64位重新分析

image-20211229162321232

xxtea 但是改了一下delta和rounds 网上随便找个脚本即可

posted @ 2021-12-29 16:28  FW_ltlly  阅读(75)  评论(0编辑  收藏  举报