De1CTF 2019 (二)

Last updated on January 27, 2024 am

signal-vm signal-vm-delta

虽然同属于2019年的De1CTF,但是这两道题却能学到很多东西并且都是vm类型,值得再开一篇细细的记录一下。

signal-vm

整体分析

题目的整体逻辑比较简单,输入,然后fork一个子进程,子进程执行loc_40a4ca函数,父进程执行sub_400b60函数。

先跟去子进程函数看看

发现一大堆非法指令,在一大堆非法指令上面调用了一个ptrace函数,并且参数是0,0,0,0即相当于ptrace(PTRACE_TRACEME,0,0,0),也就是子进程希望有一个父进程来调试自己。

那么跳去父进程的函数sub_400B6D看看,果然也调用了ptrace函数

PTRACE函数

再继续往下之前,需要先了解PTRACE函数,ptrace()系统调用能提供追踪进程执行状态的功能。ptrace()系统调用为一个进程提供了观察控制另一个进程的执行过程的能力,同时也提供检查改变另一个进程的内存值以及相关注册信息。其中,被控制的进程被称为tracee,控制进程被称为tracer

该函数签名如下

1
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);

request: 要执行的操作类型;
pid: 被追踪的目标进程ID;
addr: 被监控的目标内存地址;
data: 保存读取出或者要写入的数据。

通过ptrace系统调用可以让一个进程进入Traced状态,让一个进程进入Traced状态可以通过两种方式:

  • tracee进程调用ptrace系统调用,并在request参数处传递PTRACE_TRACEME这个值,表示想要被tracer进程追踪。通过这种方式的进程想要进入Traced状态有两种方式:
    • 主动调用exec系列的系统调用;
    • tracer发送进入Traced状态的相关信号。
  • tracer进程调用ptrace系统调用,并在request参数处传递PTRACE_ATTACH这个值,并给出tracee进程的pid,从而让tracee进程进入Traced状态。

在这道题目中,父进程采取tracer发送进入Traced状态的相关信号的方式来调试子进程。

ptrace函数中第一个枚举类型的参数也值得说道,一般有如下取值

enum func example
PTRACE_TRACEME 子进程唯一使用,表示希望得到父进程的调试,可用于反调试 ptrace(PTRACE_TRACEME, i_pid, NULL, NULL)|
PTRACE_PEEKTEXT 父进程读出子进程内存中的一个字节数据,子进程由pid给出,地址由addr给出 data = ptrace(PTRACE_PEEKTEXT, i_pid, addr,NULL)
PTRACE_PEEKDATA 同上 同上
PTRACE_POKETEXT 父进程写入子进程内存中的一个字节数据,子进程由pid给出,地址由addr给出,数据由data给出 ptrace(PTRACE_POKETEXT, i_pid, addr, data)
PTRACE_POKEDATA 同上 同上
PTRACE_PEEKUSR 父进程从子进程的user字段读出一个字节,偏移量为addr,user字段是一个user_regs_struct结构体 orig_rax = ptrace(PTRACE_PEEKUSER, pid, 8 * ORIG_RAX, NULL)
PTRACE_POKEUSR 父进程向子进程的user字段写入一个字节,偏移量为addr,数据为data,user字段是一个user_regs_struct结构体 ptrace(PTRACE_PEEKUSER, pid, 8 * ORIG_RAX, data)
PTRACE_CONT 父进程向子进程发送继续运行信号,当data参数不为零时,data将会被解释为一个signal(信号),传递给被跟踪进程 ptrace(PTRACE_CONT, pid, 0, 0)
PTRACE_SYSCALL 同上 同上
PTRACE_KILL 父进程杀死子进程 ptrace(PTRACE_KILL, pid, 0, 0)
PTRACE_ATTACH 尝试附加到pid指定的进程上。附加成功后,目标进程将处于挂起状态。子进程进程会发送SIGSTOP信号,父进程需要调用waitpid(2)以接收此信号 ptrace(PTRACE_ATTACH, pid, NULL, NULL)
PTRACE_GETREGS 父进程读出子进程寄存器数据,存放至data处,是一个struct user_regs_struct结构体 ptrace(PTRACE_GETREGS, pid, 0, regs)
PTRACE_SETREGS 父进程写入子进程寄存器数据,数据由data提供,是一个struct user_regs_struct结构体 ptrace(PTRACE_GETREGS, pid, 0, regs)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct user_regs_struct
{
__extension__ unsigned long long int r15;
__extension__ unsigned long long int r14;
__extension__ unsigned long long int r13;
__extension__ unsigned long long int r12;
__extension__ unsigned long long int rbp;
__extension__ unsigned long long int rbx;
__extension__ unsigned long long int r11;
__extension__ unsigned long long int r10;
__extension__ unsigned long long int r9;
__extension__ unsigned long long int r8;
__extension__ unsigned long long int rax;
__extension__ unsigned long long int rcx;
__extension__ unsigned long long int rdx;
__extension__ unsigned long long int rsi;
__extension__ unsigned long long int rdi;
__extension__ unsigned long long int orig_rax;
__extension__ unsigned long long int rip;
__extension__ unsigned long long int cs;
__extension__ unsigned long long int eflags;
__extension__ unsigned long long int rsp;
__extension__ unsigned long long int ss;
__extension__ unsigned long long int fs_base;
__extension__ unsigned long long int gs_base;
__extension__ unsigned long long int ds;
__extension__ unsigned long long int es;
__extension__ unsigned long long int fs;
__extension__ unsigned long long int gs;
};

struct user
{
struct user_regs_struct regs;
// other fields
}

而本题就基于ptrace函数实现了一个vm,具体流程如下:

  1. 子进程调用ptrace(PTRACE_TRACEME,0,0,0)函数表示希望被调试

  2. 子进程执行非法指令,发出信号

  3. 父进程调用wait函数截获子进程的异常信号,wait()函数的参数是子进程的返回状态,第一个字节如果是0x7f则表示子进程异常返回,第二个字节是返回值,eg: exit(2)则第二个字节为02,子进程出现异常的时候第二个字节是linux的异常信号码。同时调用ptrace函数得到子进程的寄存器中rip的值(user_regs_struct结构体的第16位就是rip)

    如下则是所有的异常码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    SIGHUP       1          /* Hangup (POSIX).  */                          终止进程     终端线路挂断
    SIGINT 2 /* Interrupt (ANSI). */ 终止进程 中断进程 Ctrl+C
    SIGQUIT 3 /* Quit (POSIX). */ 建立CORE文件终止进程,并且生成core文件 Ctrl+\
    SIGILL 4 /* Illegal instruction (ANSI). */ 建立CORE文件,非法指令
    SIGTRAP 5 /* Trace trap (POSIX). */ 建立CORE文件,跟踪自陷
    SIGABRT 6 /* Abort (ANSI). */
    SIGIOT 6 /* IOT trap (4.2 BSD). */ 建立CORE文件,执行I/O自陷
    SIGBUS 7 /* BUS error (4.2 BSD). */ 建立CORE文件,总线错误
    SIGFPE 8 /* Floating-point exception (ANSI). */ 建立CORE文件,浮点异常
    SIGKILL 9 /* Kill, unblockable (POSIX). */ 终止进程 杀死进程
    SIGUSR1 10 /* User-defined signal 1 (POSIX). */ 终止进程 用户定义信号1
    SIGSEGV 11 /* Segmentation violation (ANSI). */ 建立CORE文件,段非法错误
    SIGUSR2 12 /* User-defined signal 2 (POSIX). */ 终止进程 用户定义信号2
    SIGPIPE 13 /* Broken pipe (POSIX). */ 终止进程 向一个没有读进程的管道写数据
    SIGALARM 14 /* Alarm clock (POSIX). */ 终止进程 计时器到时
    SIGTERM 15 /* Termination (ANSI). */ 终止进程 软件终止信号
    SIGSTKFLT 16 /* Stack fault. */
    SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
    SIGCHLD 17 /* Child status has changed (POSIX). */ 忽略信号 当子进程停止或退出时通知父进程
    SIGCONT 18 /* Continue (POSIX). */ 忽略信号 继续执行一个停止的进程
    SIGSTOP 19 /* Stop, unblockable (POSIX). */ 停止进程 非终端来的停止信号
    SIGTSTP 20 /* Keyboard stop (POSIX). */ 停止进程 终端来的停止信号 Ctrl+Z
    SIGTTIN 21 /* Background read from tty (POSIX). */ 停止进程 后台进程读终端
    SIGTTOU 22 /* Background write to tty (POSIX). */ 停止进程 后台进程写终端
    SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ 忽略信号 I/O紧急信号
    SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ 终止进程 CPU时限超时
    SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ 终止进程 文件长度过长
    SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ 终止进程 虚拟计时器到时
    SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ 终止进程 统计分布图用计时器到时
    SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ 忽略信号 窗口大小发生变化
    SIGPOLL SIGIO /* Pollable event occurred (System V). */
    SIGIO 29 /* I/O now possible (4.2 BSD). */ 忽略信号 描述符上可以进行I/O
    SIGPWR 30 /* Power failure restart (System V). */
    SIGSYS 31 /* Bad system call. */
    SIGUNUSED 31

    本题中只会出现四种信号分别是SIGILLSIGTRAPSIGSEGVSIGFPE,父进程就会根据他们这几个信号来执行对应的操作

  4. 根据截获的信号和从寄存器读出的rip值决定操作,同时设置rip

截屏2024-01-21 23.26.23

  1. 将设置好的rip写回子进程,同时发送继续运行的信号,然后继续等待子进程的异常

系统调用

根据以上分析可以发现,此程序父子进程之间主要是是通过ptrace以及异常信号进行通信,那么可以使用strace系统命令来进行跟踪

图中红色框圈出来的就是子进程发出的信号,可以进一步提取出来

只需要再重定向一下然后写个脚本把信号提取出来即可。

Opcode分析

有了信号,就有了对应的操作流程,那么可以尝试分析一下程序操作码是如设计的,这里选择直接将源程序打印出来,并且模拟一遍执行流程。

不过还需要注意几点

  1. 输入存放的位置,经过调试发现输入存放在Almost字符串后50个地方,那么在模拟的时候也要相应的存入。
  2. 子进程也会执行指令,比如cc,这时候rip会自动加1,在模拟的时候也要这样做(因为rip指向的就是指令执行的地址)

截屏2024-01-23 00.59.12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
from ctypes import *
from struct import pack

opcode = [6, 1, 6, 0, 0, 0, 0,
6, 1, 3, 0, 0, 0, 0,
0, 0, 0, 15,
0, 0, 0, 204, 0, 1, 3, 1, 0, 0, 0,
6, 0, 0, 3,
6, 0, 2, 0,
6, 1, 0, 50, 0, 0, 0,
204,
0, 0, 0, 2,
6, 2, 0, 0,
48, 192,
246, 248, 1, 0, 0, 0, 0, 0,
0, 0, 2, 214, 255, 255, 255,
48, 192,
246, 248, 1, 3, 70, 0, 0, 0,
0, 0, 1, 21, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 225, 1, 0,
0, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 6, 1, 4, 0, 0, 0, 0, 0, 0, 0, 17, 1, 0, 0, 6, 1, 6, 0, 0, 0, 0,
6, 1, 5, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 6, 0, 2, 3, 6, 0, 0, 2, 204, 8, 1, 0, 3, 0, 0, 0, 204, 1, 0, 0, 2,
6, 0, 2, 0, 6, 0, 0, 5, 204, 0, 0, 0, 2, 6, 0, 2, 0, 6, 1, 0, 50, 0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 1, 0, 6, 0,
2, 5, 6, 0, 0, 2, 204, 8, 1, 0, 3, 0, 0, 0, 204, 1, 0, 0, 2, 6, 0, 2, 0, 6, 0, 0, 4, 204, 0, 0, 0, 2, 6, 0, 2,
0, 6, 1, 0, 0, 0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 2, 0, 6, 0, 0, 1, 204, 2, 0, 0, 2, 204, 4, 1, 0, 0, 1, 0, 0,
204, 0, 0, 6, 0, 204, 4, 1, 6, 0, 1, 0, 0, 6, 0, 0, 5, 204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 5, 0, 48, 192, 246,
248, 1, 5, 6, 0, 0, 0, 0, 0, 6, 92, 255, 255, 255, 6, 0, 2, 3, 6, 0, 0, 2, 204, 8, 1, 0, 3, 0, 0, 0, 204, 1,
0, 0, 2, 6, 0, 2, 0, 6, 0, 0, 4, 204, 0, 0, 0, 2, 6, 0, 2, 0, 6, 1, 0, 150, 0, 0, 0, 204, 0, 0, 0, 2, 6, 0, 1,
6, 6, 32, 0, 1, 6, 0, 0, 4, 204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 48, 192, 246, 248, 1, 4, 6, 0, 0, 0, 0, 0,
6, 236, 254, 255, 255, 6, 0, 0, 3, 204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 3, 0, 48, 192, 246, 248, 1, 3, 9, 0, 0, 0,
0, 0, 6, 189, 254, 255, 255, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 6, 0, 0, 3, 6, 0, 2, 0, 6, 1, 0, 150,
0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 1, 0, 6, 0, 0, 3, 6, 0, 2, 0, 6, 1, 0, 250, 0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 0,
0, 48, 192, 246, 248, 0, 1, 0, 0, 0, 1, 21, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 6, 0, 0, 3,
204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 3, 0, 48, 192, 246, 248, 1, 3, 69, 0, 0, 0, 0, 0, 6, 154, 255, 255, 255, 6, 1,
0, 1, 0, 0, 0, 201, 195]

signal = [4, 4, 11, 4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 5,
4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4,
5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 5, 4, 4, 4, 5, 4, 8, 11, 8, 11, 4, 11]

vm_regs = [0, 0, 0, 0, 0, 0, 0]

rip = 0
regs_16 = 0

v14 = 0

Almost = [65, 108, 109, 111, 115, 116, 32, 104, 101, 97, 118, 101, 110, 32, 119, 101, 115, 116, 32, 118, 105, 114, 103,
105, 110, 105, 97, 44, 32, 98, 108, 117, 101, 32, 114, 105, 100, 103, 101, 32, 109, 111, 117, 110, 116, 97,
105, 110, 115, 0xab, 0xcd, 0xab, 0xcd, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0, 0xff, 0xff, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0]

dword = 0

if_cc = 0
for i in signal:
rip = regs_16
if opcode[rip] == 0xcc:
print('cc'.rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)}')
rip += 1
regs_16 += 1
if opcode[rip] == 48 and opcode[rip + 1] == 192:
print(f'{hex(48)[2:]}{hex(192)[2:]}'.rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)}')
rip += 2
# if_cc = 1
regs_16 += 2

# if opcode[rip] == 0x00 and opcode[rip + 1] == 0x00 and opcode[rip + 2] == 0x02 and opcode[rip + 3] == 214:
# print(f'{hex(0)[2:].zfill(2)}{hex(0)[2:].zfill(2)}{hex(2)[2:].zfill(2)}{hex(214)[2:]}'.rjust(16), end=' ')
# print(f'{hex(rip)[2:].zfill(4)}')
# rip += 4
# # if_cc = 1
# regs_16 += 4


if i == 4:
if opcode[rip + 1] == 1:
v14 = c_int32(int(pack('<BBBB', opcode[rip+6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),base=16)).value
regs_16 += 7
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
else:
v14 = opcode[rip + 3]
regs_16 += 4
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 4]]).rjust(16), end=' ')

if opcode[rip + 1] == 1:
vm_regs[opcode[rip + 2]] = v14
print(f'{hex(rip)[2:].zfill(4)} mov vm_regs_{opcode[rip + 2]},{v14}')

if opcode[rip + 1] == 2:
print(f'{hex(rip)[2:].zfill(4)} mov vm_regs_{opcode[rip + 2]},Almost{[vm_regs[v14]]}')
vm_regs[opcode[rip + 2]] = Almost[vm_regs[v14]]

if opcode[rip + 1] == 32:
Almost[vm_regs[opcode[rip + 2]]] = vm_regs[v14]
print(f'{hex(rip)[2:].zfill(4)} mov Almost{[vm_regs[opcode[rip + 3]]]},vm_regs_{v14}')

if opcode[rip + 1] == 0:
print(f'{hex(rip)[2:].zfill(4)} mov vm_regs_{opcode[rip + 2]},vm_regs_{v14}')
vm_regs[opcode[rip + 2]] = vm_regs[v14]


if i == 5:
if opcode[rip + 1] == 1:
regs_16 += 7
v14 = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),base=16)).value
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
if opcode[rip + 1] == 0:
regs_16 += 4
v14 = vm_regs[opcode[rip + 3]]
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 4]]).rjust(16), end=' ')

if opcode[rip] == 0:
# print('debug:',i)
vm_regs[opcode[rip + 2]] += v14
print(f'{hex(rip)[2:].zfill(4)} add vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 1:
vm_regs[opcode[rip + 2]] -= v14
print(f'{hex(rip)[2:].zfill(4)} sub vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 2:
vm_regs[opcode[rip + 2]] *= v14
print(f'{hex(rip)[2:].zfill(4)} mul vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 3:
vm_regs[opcode[rip + 2]] /= v14
print(f'{hex(rip)[2:].zfill(4)} div vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 4:
vm_regs[opcode[rip + 2]] %= v14
print(f'{hex(rip)[2:].zfill(4)} mod vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 5:
vm_regs[opcode[rip + 2]] |= v14
print(f'{hex(rip)[2:].zfill(4)} or vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 6:
vm_regs[opcode[rip + 2]] ^= v14
print(f'{hex(rip)[2:].zfill(4)} xor vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 7:
vm_regs[opcode[rip + 2]] <<= v14
print(f'{hex(rip)[2:].zfill(4)} shl vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

if opcode[rip] == 8:
vm_regs[opcode[rip + 2]] >>= v14
print(f'{hex(rip)[2:].zfill(4)} shr vm_regs_{opcode[rip + 2]},vm_regs_{opcode[rip + 3]}')
continue

# else:
# print(f'{hex(rip)[2:].zfill(4)} ')

if i == 8:
if opcode[rip + 2] == 1:
v14 = (rip & 0xffff0000) >> 32
dword = vm_regs[opcode[rip + 3]] - v14
regs_16 += 8
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 8]]), end=' ')
print(f'{hex(rip)[2:].zfill(4)} cmp vm_regs_{opcode[rip + 3]},{(opcode[rip+4])}')

if opcode[rip + 2] == 0:
v14 = opcode[rip + 4]
dword = vm_regs[opcode[rip + 3]] - opcode[rip + 4]
regs_16 += 5
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 5]]), end=' ')
print(f'{hex(rip)[2:].zfill(4)} cmp vm_regs{opcode[rip + 3]},vm_regs{opcode[rip + 4]}')

if i == 0xb:
if opcode[rip + 2] == 0:
# regs_16 += opcode[rip + 3]
regs_16 += c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),base=16)).value
# regs_16 += opcode[rip:rip + 3]
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 4]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jmp {hex(regs_16)[2:].zfill(4)}')

if opcode[rip + 2] == 1:
if dword > 0:
regs_16 += 7
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},je {hex(regs_16)[2:].zfill(4)}')
else:
regs_16 += c_int32(int(pack('<BBBB', opcode[rip+6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),base=16)).value
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + opcode[rip + 3]]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} je {hex(regs_16)[2:].zfill(4)}')

if opcode[rip + 2] == 2:
if dword > 0:
regs_16 += c_int32(int(pack('<BBBB', opcode[rip+6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),base=16)).value
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jg {hex(regs_16)[2:].zfill(4)}')
else:
regs_16 += 7
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')

if opcode[rip + 2] == 3:
if dword <= 0:
regs_16 += 7
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jel {hex(regs_16)[2:].zfill(4)}')
else:
regs_16 += opcode[rip + 3]
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:opcode[rip + 3]]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jg {hex(regs_16)[2:].zfill(4)}')

if opcode[rip + 2] == 4:
if dword < 0:
regs_16 += 7
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jl {hex(regs_16)[2:].zfill(4)}')
else:
regs_16 += opcode[rip + 3]
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:opcode[rip + 3]]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jeg {hex(regs_16)[2:].zfill(4)}')

if opcode[rip + 2] == 5:
if dword >= 0:
regs_16 += 7
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jeg {hex(regs_16)[2:].zfill(4)}')
else:
regs_16 += opcode[rip + 3]
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:opcode[rip + 3]]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jl {hex(regs_16)[2:].zfill(4)}')

if opcode[rip + 2] == 6:
if dword > 0:
regs_16 += 7
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jg {hex(regs_16)[2:].zfill(4)}')
else:
regs_16 += opcode[rip + 3]
print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:opcode[rip + 3]]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)},jnl {hex(regs_16)[2:].zfill(4)}')


如下就是实际执行的代码以及对应的汇编操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
	06010600000000 0000 mov vm_regs_6,0
06010300000000 0007 mov vm_regs_3,0
0000000f 000e jmp 001d
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[50]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[51]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[52]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[53]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[54]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[55]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[56]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[57]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[58]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 003f jg 0015
cc 0015
00010301000000 0016 add vm_regs_3,vm_regs_1
06000003 001d mov vm_regs_0,vm_regs_3
06000200 0021 mov vm_regs_2,vm_regs_0
06010032000000 0025 mov vm_regs_0,50
cc 002c
00000002 002d add vm_regs_0,vm_regs_2
06020000 0031 mov vm_regs_0,Almost[59]
30c0 0035
f6f8010000000000 0037 cmp vm_regs_0,0
000002d6ffffff 30c0 0046
f6f80103 46000000 004c mov vm_regs_0,vm_regs_0
00000115 0050 mov vm_regs_1,vm_regs_21

最后几条指令可能会有问题,不过并不重要。

有了机器码以及对应的汇编语句,现在翻译原来那一大堆指令也就比较简单了。而且通过对原伪代码分析,可以将信号分为四个类,

case 4:mov 类

case 5:逻辑运算

case 8:比较

case 11: 跳转

反汇编

熟悉了机器码以及对应的汇编后,就可以开始进行反汇编它的opcode了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
from ctypes import c_int32
from struct import pack

opcode = [6, 1, 6, 0, 0, 0, 0,
6, 1, 3, 0, 0, 0, 0,
0, 0, 0, 15, 0, 0, 0,
204,
0, 1, 3, 1, 0, 0, 0,
6, 0, 0, 3,
6, 0, 2, 0,
6, 1, 0, 50, 0, 0, 0,
204,
0, 0, 0, 2,
6, 2, 0, 0,
48, 192,
246, 248, 1, 0, 0, 0, 0, 0,
0, 0, 2, 214, 255, 255, 255,
48, 192,
246, 248, 1, 3, 70, 0, 0, 0,
0, 0, 1, 21, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 225, 1, 0,
0, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 6, 1, 4, 0, 0, 0, 0, 0, 0, 0, 17, 1, 0, 0, 6, 1, 6, 0, 0, 0, 0,
6, 1, 5, 0, 0, 0, 0, 0, 0, 0, 161, 0, 0, 0, 6, 0, 2, 3, 6, 0, 0, 2, 204, 8, 1, 0, 3, 0, 0, 0, 204, 1, 0, 0, 2,
6, 0, 2, 0, 6, 0, 0, 5, 204, 0, 0, 0, 2, 6, 0, 2, 0, 6, 1, 0, 50, 0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 1, 0, 6, 0,
2, 5, 6, 0, 0, 2, 204, 8, 1, 0, 3, 0, 0, 0, 204, 1, 0, 0, 2, 6, 0, 2, 0, 6, 0, 0, 4, 204, 0, 0, 0, 2, 6, 0, 2,
0, 6, 1, 0, 0, 0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 2, 0, 6, 0, 0, 1, 204, 2, 0, 0, 2, 204, 4, 1, 0, 0, 1, 0, 0,
204, 0, 0, 6, 0, 204, 4, 1, 6, 0, 1, 0, 0, 6, 0, 0, 5, 204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 5, 0, 48, 192, 246,
248, 1, 5, 6, 0, 0, 0, 0, 0, 6, 92, 255, 255, 255, 6, 0, 2, 3, 6, 0, 0, 2, 204, 8, 1, 0, 3, 0, 0, 0, 204, 1,
0, 0, 2, 6, 0, 2, 0, 6, 0, 0, 4, 204, 0, 0, 0, 2, 6, 0, 2, 0, 6, 1, 0, 150, 0, 0, 0, 204, 0, 0, 0, 2, 6, 0, 1,
6, 6, 32, 0, 1, 6, 0, 0, 4, 204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 4, 0, 48, 192, 246, 248, 1, 4, 6, 0, 0, 0, 0, 0,
6, 236, 254, 255, 255, 6, 0, 0, 3, 204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 3, 0, 48, 192, 246, 248, 1, 3, 9, 0, 0, 0,
0, 0, 6, 189, 254, 255, 255, 6, 1, 3, 0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 6, 0, 0, 3, 6, 0, 2, 0, 6, 1, 0, 150,
0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 1, 0, 6, 0, 0, 3, 6, 0, 2, 0, 6, 1, 0, 250, 0, 0, 0, 204, 0, 0, 0, 2, 6, 2, 0,
0, 48, 192, 246, 248, 0, 1, 0, 0, 0, 1, 21, 0, 0, 0, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, 0, 0, 6, 0, 0, 3,
204, 0, 1, 0, 1, 0, 0, 0, 6, 0, 3, 0, 48, 192, 246, 248, 1, 3, 69, 0, 0, 0, 0, 0, 6, 154, 255, 255, 255, 6, 1,
0, 1, 0, 0, 0, 201, 195]

rip = 0
vm_regs = [0, 0, 0, 0, 0, 0, 0]
cc_flag = 0
cmp_flag = 0
while 1:
if rip >= len(opcode):
break
# 检查标志位
if opcode[rip] == 0xcc:
# print('cc'.rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} cc')
cc_flag = 1
rip += 1
elif opcode[rip] == 0x30 and opcode[rip + 1] == 0xc0:
# print(f'{hex(48)[2:]}{hex(192)[2:]}'.rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} 30c0')
cmp_flag = 1
rip += 2

# 存取值
if opcode[rip] == 6:
# 立即数
if opcode[rip + 1] == 1:
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
v14 = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
print(f'{hex(rip)[2:].zfill(4)} mov vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue
# 寄存器
if opcode[rip + 1] == 0:
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 4]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} mov vm_regs_{opcode[rip + 2]}\tvm_regs_{opcode[rip + 3]}')
rip += 4
continue
# 取值
if opcode[rip + 1] == 2:
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 4]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} mov vm_regs_{opcode[rip + 2]}\tAlmost[vm_regs_{opcode[rip + 3]}]')
rip += 4
continue
# 存值
if opcode[rip + 1] == 32:
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 4]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} mov Almost[vm_regs_{opcode[rip + 2]}]\tvm_regs_{opcode[rip + 3]}')
rip += 4
continue

# 逻辑运算
if cc_flag == 1:
v14 = 0
cc_flag = 0
# 立即数运算
if opcode[rip + 1] == 1:
v14 = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
if opcode[rip] == 0:
print(f'{hex(rip)[2:].zfill(4)} add vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 1:
print(f'{hex(rip)[2:].zfill(4)} sub vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 2:
print(f'{hex(rip)[2:].zfill(4)} mul vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 3:
print(f'{hex(rip)[2:].zfill(4)} div vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 4:
print(f'{hex(rip)[2:].zfill(4)} mod vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 5:
print(f'{hex(rip)[2:].zfill(4)} or vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 6:
print(f'{hex(rip)[2:].zfill(4)} and vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 7:
print(f'{hex(rip)[2:].zfill(4)} xor vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 8:
print(f'{hex(rip)[2:].zfill(4)} shl vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue

if opcode[rip] == 9:
print(f'{hex(rip)[2:].zfill(4)} shr vm_regs_{opcode[rip + 2]}\t{v14}')
rip += 7
continue
# 寄存器运算
if opcode[rip + 1] == 0:
v14 = opcode[rip + 3]
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 4]]).rjust(16), end=' ')
if opcode[rip] == 0:
print(f'{hex(rip)[2:].zfill(4)} add vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 1:
print(f'{hex(rip)[2:].zfill(4)} sub vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 2:
print(f'{hex(rip)[2:].zfill(4)} mul vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 3:
print(f'{hex(rip)[2:].zfill(4)} div vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 4:
print(f'{hex(rip)[2:].zfill(4)} mod vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 5:
print(f'{hex(rip)[2:].zfill(4)} or vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 6:
print(f'{hex(rip)[2:].zfill(4)} and vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 7:
print(f'{hex(rip)[2:].zfill(4)} xor vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 8:
print(f'{hex(rip)[2:].zfill(4)} shl vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

if opcode[rip] == 9:
print(f'{hex(rip)[2:].zfill(4)} shr vm_regs_{opcode[rip + 2]}\tvm_regs_{v14}')
rip += 4
continue

# 比较
if cmp_flag == 1:
cmp_flag = 0
if opcode[rip + 2] == 1:
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 8]]), end=' ')
num = c_int32(int(pack('<BBBB', opcode[rip + 7], opcode[rip + 6], opcode[rip + 5], opcode[rip + 4]).hex(),
base=16)).value
print(f'{hex(rip)[2:].zfill(4)} cmp vm_regs_{opcode[rip + 3]}\t{num}')
rip += 8
# print(f'debug:{opcode[rip:rip+8]}')
continue
if opcode[rip + 2] == 0:
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 5]]), end=' ')
print(f'{hex(rip)[2:].zfill(4)} cmp vm_regs_{opcode[rip + 3]}\tvm_regs_{opcode[rip + 4]}')
rip += 5
continue

# 跳转
if opcode[rip] == 0:
if opcode[rip + 2] == 0:
addr = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jmp {hex(addr + rip)}')
rip += 7
continue

if opcode[rip + 2] == 1:
num = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jeq {hex(rip + num)}')
rip += 7
continue

if opcode[rip + 2] == 2:
num = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jg {hex(rip + num)}')
rip += 7
continue

if opcode[rip + 2] == 3:
num = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jg {hex(rip + num)}')
rip += 7
continue

if opcode[rip + 2] == 4:
num = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jeg {hex(rip + num)}')
rip += 7
continue

if opcode[rip + 2] == 5:
num = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jl {hex(rip + num)}')
rip += 7
continue

if opcode[rip + 2] == 6:
num = c_int32(int(pack('<BBBB', opcode[rip + 6], opcode[rip + 5], opcode[rip + 4], opcode[rip + 3]).hex(),
base=16)).value
# print(''.join([hex(k)[2:].zfill(2) for k in opcode[rip:rip + 7]]).rjust(16), end=' ')
print(f'{hex(rip)[2:].zfill(4)} jle {hex(rip + num)}')
rip += 7
continue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
0000 mov vm_regs_6	0
0007 mov vm_regs_3 0
000e jmp 0x1d

Label_1:
0015 cc
0016 add vm_regs_3 1

001d mov vm_regs_0 vm_regs_3
0021 mov vm_regs_2 vm_regs_0
0025 mov vm_regs_0 50
002c cc
002d add vm_regs_0 vm_regs_2
0031 mov vm_regs_0 Almost[vm_regs_0] # Almost是原始字符串 这里加50 得到输入的地址
0035 30c0
0037 cmp vm_regs_0 0 # 比较是否是字符串结束
003f jg 0x15 # jg Label_1

0046 30c0
0048 cmp vm_regs_3 70 # 比较长度 长度70
0050 jeq 0x65 # jmp Label_2
0057 mov vm_regs_0 0 # 失败 ret(0)
005e jmp 0x23f

Label_2:
0065 mov vm_regs_3 0 # vm_regs_3 = i
006c jmp 0x1ac # jmp Label_3

Label_4:
0073 mov vm_regs_4 0 # vm_regs_4 = j
007a jmp 0x18b # jmp Label_5

Label_6:
0081 mov vm_regs_6 0 # tmp = 0
0088 mov vm_regs_5 0 # vm_regs_5 = k
008f jmp 0x130 # jmp Label_7

Label_8
0096 mov vm_regs_2 vm_regs_3
009a mov vm_regs_0 vm_regs_2
009e cc
009f shl vm_regs_0 3 # i << 3
00a6 cc
00a7 sub vm_regs_0 vm_regs_2 # (i << 3) - i
00ab mov vm_regs_2 vm_regs_0 # vm_regs_2 = (i << 3) - i
00af mov vm_regs_0 vm_regs_5
00b3 cc
00b4 add vm_regs_0 vm_regs_2
00b8 mov vm_regs_2 vm_regs_0 # vm_regs_2 = k + 7 * i
00bc mov vm_regs_0 50
00c3 cc
00c4 add vm_regs_0 vm_regs_2 # vm_regs_0 = k + 7 * i + 50
00c8 mov vm_regs_1 Almost[vm_regs_0] # 得到(i,k)
00cc mov vm_regs_2 vm_regs_5 # vm_regs_2 = k
00d0 mov vm_regs_0 vm_regs_2
00d4 cc
00d5 shl vm_regs_0 3 # vm_regs_0 = k << 3
00dc cc
00dd sub vm_regs_0 vm_regs_2 # vm_regs_0 = 7 * k
00e1 mov vm_regs_2 vm_regs_0 # vm_regs_2 = 7 * k
00e5 mov vm_regs_0 vm_regs_4 # vm_regs_0 = j
00e9 cc
00ea add vm_regs_0 vm_regs_2 # vm_regs_0 = j + 7 * k
00ee mov vm_regs_2 vm_regs_0 # vm_regs_2 = j + 7 * k
00f2 mov vm_regs_0 0
00f9 cc
00fa add vm_regs_0 vm_regs_2 # vm_regs_0 = j + 7 * k
00fe mov vm_regs_2 Almost[vm_regs_0] # vm_regs_2 = Almost[j + 7 * k]
0102 mov vm_regs_0 vm_regs_1 # vm_regs_0 = (k,j)
0106 cc
0107 mul vm_regs_0 vm_regs_2 # vm_regs_0 = Input(i,k) * Src(k,j)
010b cc
010c mod vm_regs_0 256 # vm_regs_0 = vm_regs_0 % 256
0113 cc
0114 add vm_regs_6 vm_regs_0 # tmp += vm_regs_0
0118 cc
0119 mod vm_regs_6 256 # tmp %= 256
0120 mov vm_regs_0 vm_regs_5 # vm_regs_0 = k
0124 cc
0125 add vm_regs_0 1 # vm_regs_0 += 1
012c mov vm_regs_5 vm_regs_0 # k += 1

Label_7:
0130 30c0
0132 cmp vm_regs_5 6
013a jle 0x96 # jmp Label_8

0141 mov vm_regs_2 vm_regs_3 # vm_regs_2 = i
0145 mov vm_regs_0 vm_regs_2
0149 cc
014a shl vm_regs_0 3
0151 cc
0152 sub vm_regs_0 vm_regs_2
0156 mov vm_regs_2 vm_regs_0 # vm_regs_2 = 7 * i
015a mov vm_regs_0 vm_regs_4 # vm_regs_0 = j
015e cc
015f add vm_regs_0 vm_regs_2 # vm_regs_0 = 7 * i + j
0163 mov vm_regs_2 vm_regs_0
0167 mov vm_regs_0 150
016e cc
016f add vm_regs_0 vm_regs_2 # vm_regs_0 = 7 * i + j + 150
0173 mov vm_regs_1 vm_regs_6 # vm_regs_1 = tmp
0177 mov Almost[vm_regs_0] vm_regs_1 # Almost[7 * i + j + 150] = tmp
017b mov vm_regs_0 vm_regs_4
017f cc
0180 add vm_regs_0 1
0187 mov vm_regs_4 vm_regs_0 # j += 1

Label_5:
018b 30c0
018d cmp vm_regs_4 6
0195 jle 0x81 # jmp label_6

019c mov vm_regs_0 vm_regs_3
01a0 cc
01a1 add vm_regs_0 1
01a8 mov vm_regs_3 vm_regs_0 # k += 1

Label_3
01ac 30c0
01ae cmp vm_regs_3 9
01b6 jle 0x73 # jmp Label_4

# 检验
01bd mov vm_regs_3 0 # i = 0
01c4 jmp 0x227 # jmp Label_9

Label_10
01cb mov vm_regs_0 vm_regs_3
01cf mov vm_regs_2 vm_regs_0
01d3 mov vm_regs_0 150
01da cc
01db add vm_regs_0 vm_regs_2 # vm_regs_0 = i + 150
01df mov vm_regs_1 Almost[vm_regs_0] # vm_regs_1 = Almost[i + 150]
01e3 mov vm_regs_0 vm_regs_3
01e7 mov vm_regs_2 vm_regs_0
01eb mov vm_regs_0 250
01f2 cc
01f3 add vm_regs_0 vm_regs_2 # vm_regs_0 = i + 250
01f7 mov vm_regs_0 Almost[vm_regs_0] # vm_regs_0 = Almost[i + 250]
01fb 30c0
01fd cmp vm_regs_1 vm_regs_0
0202 jeq 0x217

0209 mov vm_regs_0 0
0210 jmp 0x23f

0217 mov vm_regs_0 vm_regs_3
021b cc
021c add vm_regs_0 1
0223 mov vm_regs_3 vm_regs_0
0227 30c0
0229 cmp vm_regs_3 69
0231 jle 0x1cb # jmp Label_10

0238 mov vm_regs_0 1

阅读汇编,发现就是简单做了一个矩阵相乘的运算,我们输入70个字符相当于10*7的矩阵,然后和原始49个字符的7*7矩阵相乘,再作比较

解题

最后就是简单用z3来解方程了,不能直接算逆矩阵是因为原来运算都是字节型的,会有数据损失

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from z3 import *

# [10,7] * [7,7] = [10,7]
enc = [[0xD6, 0x4D, 0x2D, 0x85, 0x77, 0x97, 0x60],
[0x62, 0x2B, 0x88, 0x86, 0xCA, 0x72, 0x97],
[0xEB, 0x89, 0x98, 0xF3, 0x78, 0x26, 0x83],
[0x29, 0x5E, 0x27, 0x43, 0xFB, 0xB8, 0x17],
[0x7C, 0xCE, 0x3A, 0x73, 0xCF, 0xFB, 0xC7],
[0x9C, 0x60, 0xAF, 0x9C, 0xC8, 0x75, 0xCD],
[0x37, 0x7B, 0x3B, 0x9B, 0x4E, 0xC3, 0xDA],
[0xD8, 0xCE, 0x71, 0x2B, 0x30, 0x68, 0x46],
[0x0B, 0xFF, 0x3C, 0xF1, 0xF1, 0x45, 0xC4],
[0xD0, 0xC4, 0xFF, 0x51, 0xF1, 0x88, 0x51]]

src = [[0x41, 0x6C, 0x6D, 0x6F, 0x73, 0x74, 0x20],
[0x68, 0x65, 0x61, 0x76, 0x65, 0x6E, 0x20],
[0x77, 0x65, 0x73, 0x74, 0x20, 0x76, 0x69],
[0x72, 0x67, 0x69, 0x6E, 0x69, 0x61, 0x2C],
[0x20, 0x62, 0x6C, 0x75, 0x65, 0x20, 0x72],
[0x69, 0x64, 0x67, 0x65, 0x20, 0x6D, 0x6F],
[0x75, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x73]]

input_ = [[BitVec('input_%s_%s' % (i, j), 8) for i in range(7)] for j in range(10)]
s = Solver()

for i in range(10):
for j in range(7):
tmp = 0
for k in range(7):
# t = src[k][j]
tmp += input_[i][k] * src[k][j]
s.add(tmp == enc[i][j])

s.check()
m = s.model()

for i in input_:
for k in i:
print(chr(m[k].as_long()),end='')
# de1ctf{7h3n_f4r3_u_w3ll_5w337_cr4g13_HILL_wh3r3_0f3n_71m35_1_v3_r0v3d}

signal-vm-delta

待做>_<


De1CTF 2019 (二)
http://example.com/2024/01/21/De1CTF 2019 2/
Author
yring
Posted on
January 21, 2024
Licensed under