逆向杂题选做

做题

[SWPUCTF 2021 新生赛]astJS

json逆向

json可转为js代码

1
2
$ esgenerate *.file>*.js
node *.js

[NSSCTF 2022 Spring Recruit]easy Pe

右键看描述,发现利用BAT2EXE生成。上网搜发现直接改为.7z解压就得.bat,分析程序可知123123。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@echo off
set /p input =please input flag:
set input|findstr "\<123123\>"
cls
if "%errorlevel%" == "0" ( goto 0 ) ELSE (goto 1)
exit
:0
echo good_job!
pause
exit
:1
echo sorry...
pause
exit

[GDOUCTF 2023]L!s!

BinDiff使用方法:

用ida生成两个文件的.i64分析文件,在BinDiff中New Diff。看函数匹配中有个函数只有0.8的匹配度。ida打开,分析主要逻辑,发现有个变量不知道,用赛博厨子爆破:

1
[{"op":"From Hex","args":["Auto"]},{"op":"XOR Brute Force","args":[1,100,0,"Standard",false,true,false,""]}]

[NISACTF 2022]鸣神的国土

给的.s代码,在Kali Linux中用as编译成elf:

1
as re -o re1

丢IDA,发现ROT13编码,解码+Base64得flag。

点击就送的逆向题

.s编译成elf,发现简单逻辑。

[MoeCTF 2022]EzRisc-V

Risc-V指令集用Ghidra打开,可以反汇编为C。

1
2
From_Hex('Auto')
XOR({'option':'Hex','string':'39'},'Standard',false)

[虎符CTF 2022]fpbe

eBPF程序逆向。新装了IDA Pro 8.3非常开心,结构体识别嘎嘣脆。

关键函数寻找:main->fpbe_bpf__open_and_load->fpbe_bpf__open->fpbe_bpf__open_opts->fpbe_bpf__create_skeleton

找到这句话:s->name = "fpbe_bpf";,追一下地址,发现下面出现”.ELF“等字样。一眼丁真ELF文件。s->data_sz = 1648LL;即为该文件大小。转换为数组后Shift+e导出raw bytes到文件。

法一:照着readme装个IDA插件:https://github.com/cylance/eBPF_processor,就能看到汇编,但是只能看到汇编。

法二:利用readelf ebpf_code -all看到是Linux BPF框架,其中uprobe/func段存储得就是BPF字节码。用llvm-objdump反汇编:llvm-objdump -d ebpf_code

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
ebpf_code:	file format elf64-bpf

Disassembly of section uprobe/func:

0000000000000000 <uprobe>:
0: 79 12 68 00 00 00 00 00 r2 = *(u64 *)(r1 + 0x68)
1: 67 02 00 00 20 00 00 00 r2 <<= 0x20
2: 77 02 00 00 20 00 00 00 r2 >>= 0x20
3: 79 13 70 00 00 00 00 00 r3 = *(u64 *)(r1 + 0x70)
4: 67 03 00 00 20 00 00 00 r3 <<= 0x20
5: 77 03 00 00 20 00 00 00 r3 >>= 0x20
6: bf 34 00 00 00 00 00 00 r4 = r3
7: 27 04 00 00 c0 6d 00 00 r4 *= 0x6dc0
8: bf 25 00 00 00 00 00 00 r5 = r2
9: 27 05 00 00 88 fb 00 00 r5 *= 0xfb88
10: 0f 45 00 00 00 00 00 00 r5 += r4
11: 79 14 60 00 00 00 00 00 r4 = *(u64 *)(r1 + 0x60)
12: 67 04 00 00 20 00 00 00 r4 <<= 0x20
13: 77 04 00 00 20 00 00 00 r4 >>= 0x20
14: bf 40 00 00 00 00 00 00 r0 = r4
15: 27 00 00 00 fb 71 00 00 r0 *= 0x71fb
16: 0f 05 00 00 00 00 00 00 r5 += r0
17: 79 11 58 00 00 00 00 00 r1 = *(u64 *)(r1 + 0x58)
18: b7 00 00 00 00 00 00 00 r0 = 0x0
19: 73 0a f8 ff 00 00 00 00 *(u8 *)(r10 - 0x8) = r0
20: 7b 0a f0 ff 00 00 00 00 *(u64 *)(r10 - 0x10) = r0
21: 7b 0a e8 ff 00 00 00 00 *(u64 *)(r10 - 0x18) = r0
22: 67 01 00 00 20 00 00 00 r1 <<= 0x20
23: 77 01 00 00 20 00 00 00 r1 >>= 0x20
24: bf 10 00 00 00 00 00 00 r0 = r1
25: 27 00 00 00 8e cc 00 00 r0 *= 0xcc8e
26: 0f 05 00 00 00 00 00 00 r5 += r0
27: b7 06 00 00 01 00 00 00 r6 = 0x1
28: 18 00 00 00 95 59 73 a1 00 00 00 00 18 be 00 00 r0 = 0xbe18a1735995 ll
30: 5d 05 42 00 00 00 00 00 if r5 != r0 goto +0x42 <LBB0_5>
31: bf 35 00 00 00 00 00 00 r5 = r3
32: 27 05 00 00 bf f1 00 00 r5 *= 0xf1bf
33: bf 20 00 00 00 00 00 00 r0 = r2
34: 27 00 00 00 e5 6a 00 00 r0 *= 0x6ae5
35: 0f 50 00 00 00 00 00 00 r0 += r5
36: bf 45 00 00 00 00 00 00 r5 = r4
37: 27 05 00 00 d3 ad 00 00 r5 *= 0xadd3
38: 0f 50 00 00 00 00 00 00 r0 += r5
39: bf 15 00 00 00 00 00 00 r5 = r1
40: 27 05 00 00 84 92 00 00 r5 *= 0x9284
41: 0f 50 00 00 00 00 00 00 r0 += r5
42: 18 05 00 00 40 03 54 e5 00 00 00 00 56 a5 00 00 r5 = 0xa556e5540340 ll
44: 5d 50 34 00 00 00 00 00 if r0 != r5 goto +0x34 <LBB0_5>
45: bf 35 00 00 00 00 00 00 r5 = r3
46: 27 05 00 00 85 dd 00 00 r5 *= 0xdd85
47: bf 20 00 00 00 00 00 00 r0 = r2
48: 27 00 00 00 28 80 00 00 r0 *= 0x8028
49: 0f 50 00 00 00 00 00 00 r0 += r5
50: bf 45 00 00 00 00 00 00 r5 = r4
51: 27 05 00 00 2d 65 00 00 r5 *= 0x652d
52: 0f 50 00 00 00 00 00 00 r0 += r5
53: bf 15 00 00 00 00 00 00 r5 = r1
54: 27 05 00 00 12 e7 00 00 r5 *= 0xe712
55: 0f 50 00 00 00 00 00 00 r0 += r5
56: 18 05 00 00 a3 4d 48 74 00 00 00 00 f3 a6 00 00 r5 = 0xa6f374484da3 ll
58: 5d 50 26 00 00 00 00 00 if r0 != r5 goto +0x26 <LBB0_5>
59: bf 35 00 00 00 00 00 00 r5 = r3
60: 27 05 00 00 2c 82 00 00 r5 *= 0x822c
61: bf 20 00 00 00 00 00 00 r0 = r2
62: 27 00 00 00 43 ca 00 00 r0 *= 0xca43
63: 0f 50 00 00 00 00 00 00 r0 += r5
64: bf 45 00 00 00 00 00 00 r5 = r4
65: 27 05 00 00 8e 7c 00 00 r5 *= 0x7c8e
66: 0f 50 00 00 00 00 00 00 r0 += r5
67: bf 15 00 00 00 00 00 00 r5 = r1
68: 27 05 00 00 3a f2 00 00 r5 *= 0xf23a
69: 0f 50 00 00 00 00 00 00 r0 += r5
70: 18 05 00 00 77 72 5a 48 00 00 00 00 9c b9 00 00 r5 = 0xb99c485a7277 ll
72: 5d 50 18 00 00 00 00 00 if r0 != r5 goto +0x18 <LBB0_5>
73: 63 1a f4 ff 00 00 00 00 *(u32 *)(r10 - 0xc) = r1
74: 63 4a f0 ff 00 00 00 00 *(u32 *)(r10 - 0x10) = r4
75: 63 2a ec ff 00 00 00 00 *(u32 *)(r10 - 0x14) = r2
76: 63 3a e8 ff 00 00 00 00 *(u32 *)(r10 - 0x18) = r3
77: 18 01 00 00 43 54 46 7b 00 00 00 00 25 73 7d 0a r1 = 0xa7d73257b465443 ll
79: 7b 1a d8 ff 00 00 00 00 *(u64 *)(r10 - 0x28) = r1
80: 18 01 00 00 46 4c 41 47 00 00 00 00 3a 20 48 46 r1 = 0x4648203a47414c46 ll
82: 7b 1a d0 ff 00 00 00 00 *(u64 *)(r10 - 0x30) = r1
83: 18 01 00 00 45 21 20 59 00 00 00 00 4f 55 52 20 r1 = 0x2052554f59202145 ll
85: 7b 1a c8 ff 00 00 00 00 *(u64 *)(r10 - 0x38) = r1
86: 18 01 00 00 57 45 4c 4c 00 00 00 00 20 44 4f 4e r1 = 0x4e4f44204c4c4557 ll
88: 7b 1a c0 ff 00 00 00 00 *(u64 *)(r10 - 0x40) = r1
89: b7 06 00 00 00 00 00 00 r6 = 0x0
90: 73 6a e0 ff 00 00 00 00 *(u8 *)(r10 - 0x20) = r6
91: bf a1 00 00 00 00 00 00 r1 = r10
92: 07 01 00 00 c0 ff ff ff r1 += -0x40
93: bf a3 00 00 00 00 00 00 r3 = r10
94: 07 03 00 00 e8 ff ff ff r3 += -0x18
95: b7 02 00 00 21 00 00 00 r2 = 0x21
96: 85 00 00 00 06 00 00 00 call 0x6

0000000000000308 <LBB0_5>:
97: bf 60 00 00 00 00 00 00 r0 = r6
98: 95 00 00 00 00 00 00 00 exit

这个方法还比较友好…,exp从网上找的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import libnum
from z3 import *
r1 = Int('r1')
r2 = Int('r2')
r3 = Int('r3')
r4 = Int('r4')
s = Solver()
s.add(r3*28096 + r2*64392 + r4*29179 + r1*52366 == 209012997183893)
s.add(r3*61887 + r2*27365 + r4*44499 + r1*37508 == 181792633258816)
s.add(r3*56709 + r2*32808 + r4*25901 + r1*59154 == 183564558159267)
s.add(r3*33324 + r2*51779 + r4*31886 + r1*62010 == 204080879923831)
if s.check() == sat:
s = s.model()
flag = libnum.n2s(s[r1].as_long()) + libnum.n2s(s[r4].as_long()) + libnum.n2s(s[r2].as_long()) + libnum.n2s(s[r3].as_long())
print(flag[::-1]) # 0vR3sAlbs8pD2h53

[CISCN 2023 初赛]ezbyte

sub_404D25为main函数,sub_404C21中发现”flag{????????????????????????????????3861}“,考虑DWARF Expression。

法一:readelf -wf ./ezbyte_patch >output.txt,然后去读这部分代码:

1
2
3
4
5
6
7
8
9
10
00000040 0000000000000094 00000044 FDE cie=00000000 pc=0000000000404bf5..0000000000404c21
DW_CFA_advance_loc: 5 to 0000000000404bfa
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to 0000000000404bfd
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_val_expression: r12 (r12) (DW_OP_constu: 2616514329260088143; DW_OP_constu: 1237891274917891239; DW_OP_constu: 1892739; DW_OP_breg12 (r12): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_constu: 8502251781212277489; DW_OP_constu: 1209847170981118947; DW_OP_constu: 8971237; DW_OP_breg13 (r13): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_or; DW_OP_constu: 2451795628338718684; DW_OP_constu: 1098791727398412397; DW_OP_constu: 1512312; DW_OP_breg14 (r14): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_or; DW_OP_constu: 8722213363631027234; DW_OP_constu: 1890878197237214971; DW_OP_constu: 9123704; DW_OP_breg15 (r15): 0; DW_OP_plus; DW_OP_xor; DW_OP_xor; DW_OP_or)
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop

然后照着这个:https://dwarfstd.org/doc/DWARF5.pdf硬看,反正我看不懂。

法二:

cargo.toml:

1
2
3
4
5
6
7
8
9
10
11
12
[package]
name = "analysis"
version = "0.1.0"
edition = "2021"

[dependencies]
gimli = "0.26.1"
object = "0.29.0"

[[bin]]
name = "analysis"
path = "analysis.rs"

analysis.rs:

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
271
272
273
274
275
276
277
278
279
280
// [dependencies]
// gimli = "0.26.1"
// object = "0.29.0"

use std::{collections::HashMap, fs, fmt::Display, io::Write};
use std::process::Command;

use gimli::UnwindSection;
use object::{Object, ObjectSection};

fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut arg = std::env::args();
if arg.len() != 2 {
panic!("Argument Error!")
}
let bin_data = fs::read(arg.nth(1).unwrap())?;
let obj_file = object::File::parse(&*bin_data)?;
let data = obj_file.section_by_name(".eh_frame").unwrap();
let eh_frame = gimli::read::EhFrame::new(data.data()?, gimli::LittleEndian);
let bases = gimli::BaseAddresses::default().set_eh_frame(data.address());
let mut entries = eh_frame.entries(&bases);

let mut file = fs::OpenOptions::new().append(false).truncate(true).write(true).create(true).open("./output.c")?;
writeln!(file, "#include <stdint.h>")?;


let mut cies = HashMap::new();
while let Some(entry) = entries.next()? {
if let gimli::CieOrFde::Fde(partial) = entry {
let fde = partial.parse(|_, bases, o| {
cies.entry(o)
.or_insert_with(|| eh_frame.cie_from_offset(bases, o))
.clone()
})?;
// 通过长度过滤出我们想要的
if fde.entry_len() < 100 {
continue;
}
let mut instructions = fde.instructions(&eh_frame, &bases);
use gimli::CallFrameInstruction::*;
loop {
match instructions.next() {
Err(e) => {
println!("Failed to decode CFI instruction: {}", e);
break;
}
Ok(Some(ValExpression {
register,
expression,
})) => {
println!(
"DW_CFA_val_expression ({}, ...)",
gimli::X86_64::register_name(register).unwrap_or("{unknown}")
);
display_val_expression(register, expression, &mut file)?;
}
Ok(None) => {
break;
}

_ => {}
}
}
}
}
file.flush()?;

Command::new("gcc")
.arg("-O3")
.arg("./output.c")
.arg("-c")
.spawn()?;

Ok(())
}

#[derive(Clone, Copy)]
struct Val {
id: u64,
}

impl Val {
fn new(id: u64) -> Self {
Val { id }
}
}

struct ValGenerator {
id: u64,
}

impl ValGenerator {
fn new() -> Self {
Self { id: 0 }
}
fn next(&mut self) -> Val {
self.id += 1;
Val::new(self.id - 1)
}
}

impl Display for Val {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "v{}", self.id)
}
}

fn display_val_expression<R>(target_reg: gimli::Register, exp: gimli::Expression<R>, w: &mut dyn Write) -> Result<(), Box<dyn std::error::Error>>
where
R: gimli::Reader,
{
let mut val_generator = ValGenerator::new();
let mut ops = exp.operations(gimli::Encoding { address_size: 8, format: gimli::Format::Dwarf64, version: 5 });
let mut stack: Vec<Val> = Vec::new();
writeln!(w, "uint64_t cal_{}(uint64_t r12, uint64_t r13, uint64_t r14, uint64_t r15){{", gimli::X86_64::register_name(target_reg).unwrap())?;
writeln!(w, " uint64_t rax=0,rbx=0;")?;
loop {
if let Ok(Some(op)) = ops.next() {
match op {
gimli::Operation::Drop => {
stack.pop();
}
gimli::Operation::Pick { index } => {
let val1 = stack.get(stack.len() - 1 - index as usize).unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={};", new_val, val1)?;
stack.push(new_val);
}
gimli::Operation::Swap => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
stack.push(val1);
stack.push(val2);
}
gimli::Operation::Rot => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let val3 = stack.pop().unwrap();
stack.push(val1);
stack.push(val3);
stack.push(val2);
}
gimli::Operation::And => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}&{};", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Minus => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}-{};", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Neg => {
let val = stack.get(stack.len() - 1).unwrap();
writeln!(w, " {}=-{};", val, val)?;
}
gimli::Operation::Not => {
let val = stack.get(stack.len() - 1).unwrap();
writeln!(w, " {}=~{};", val, val)?;
}
gimli::Operation::Or => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}|{};", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Plus => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}+{};", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::PlusConstant { value } => {
let val = stack.get(stack.len() - 1).unwrap();
writeln!(w, " {}+={}ull;", val, value)?;
}
gimli::Operation::Shl => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}<<{};", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Shr => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}>>{};", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Shra => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}=(uint64_t)((int64_t){}>>(int64_t){});", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Xor => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}^{};", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Eq => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}= {}=={}?1:0;", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Ge => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}>={}?1:0;", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Gt => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}>{}?1:0;", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Le => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}<={}?1:0;", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Lt => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}<{}?1:0;", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::Ne => {
let val1 = stack.pop().unwrap();
let val2 = stack.pop().unwrap();
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}!={}?1:0;", new_val, val2, val1)?;
stack.push(new_val);
}
gimli::Operation::UnsignedConstant { value } => {
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={}ull;", new_val, value)?;
stack.push(new_val);
}
gimli::Operation::SignedConstant { value } => {
let new_val = val_generator.next();
writeln!(w, " uint64_t {}=(uint64_t){}ll;", new_val, value)?;
stack.push(new_val);
}
gimli::Operation::RegisterOffset { register, offset, base_type} => {
let new_val = val_generator.next();
writeln!(w, " uint64_t {}={};", new_val, gimli::X86_64::register_name(register).unwrap_or("{error}"))?;
stack.push(new_val);
}

_ => todo!("{:?}", op)

}
} else {
break;
}
}
assert_eq!(stack.len(), 1);
writeln!(w, " return {};", stack.pop().unwrap())?;
writeln!(w, "}}\n")?;
Ok(())
}

然后执行这个:

1
2
cargo build
cargo run -- ./ezbyte_patch

得到output.o和output.c文件。可以尝试看output.c源代码,但这个源代码真心很垃圾。选择把output.o丢IDA里。

1
2
3
4
__int64 __fastcall cal_r12(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
return (a1 + 1892739) ^ 0x35626665394D17E8i64 | (a2 + 8971237) ^ 0x65342D6530C04912i64 | (a4 + 9123704) ^ 0x6336396431BE9AD9i64 | (a3 + 1512312) ^ 0x2D393663614447B1i64;
}

回到主程序,发现汇编代码:

1
2
xor r13, r13
cmp r13, r12

也就是r12得为0。由网上wp可得exp,得flag中间部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
int main(void)
{
__int64 a1, a2, a3, a4;
a1 = 0x35626665394D17E8-1892739;
a2 = 0x65342D6530C04912-8971237;
a3 = 0x2D393663614447B1-1512312;
a4 = 0x6336396431BE9AD9-9123704;
printf("%c%c%c%c%c%c%c%c", a1 & 0xFF, (a1 >> 8) & 0xFF, (a1 >> 16) & 0xFF, (a1 >> 24) & 0xFF, (a1 >> 32) & 0xFF, (a1 >> 40) & 0xFF, (a1 >> 48) & 0xFF, (a1 >> 56) & 0xFF);
printf("%c%c%c%c%c%c%c%c", a2 & 0xFF, (a2 >> 8) & 0xFF, (a2 >> 16) & 0xFF, (a2 >> 24) & 0xFF, (a2 >> 32) & 0xFF, (a2 >> 40) & 0xFF, (a2 >> 48) & 0xFF, (a2 >> 56) & 0xFF);
printf("%c%c%c%c%c%c%c%c", a3 & 0xFF, (a3 >> 8) & 0xFF, (a3 >> 16) & 0xFF, (a3 >> 24) & 0xFF, (a3 >> 32) & 0xFF, (a3 >> 40) & 0xFF, (a3 >> 48) & 0xFF, (a3 >> 56) & 0xFF);
printf("%c%c%c%c%c%c%c%c", a4 & 0xFF, (a4 >> 8) & 0xFF, (a4 >> 16) & 0xFF, (a4 >> 24) & 0xFF, (a4 >> 32) & 0xFF, (a4 >> 40) & 0xFF, (a4 >> 48) & 0xFF, (a4 >> 56) & 0xFF);
return 0;
}

[BJDCTF2020]JustRE

VC++类程序先对事件进行注册,注册函数一般在窗口绘制前。

[HDCTF 2023]买了些什么呢

01背包板子题,但下标0或1开始比较抽象:

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
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int weight[41]={0,2,5,10,9,3,6,2,2,6,8,2,3,3,2,9,8,2,10,8,6,4,3,4,2,4,8,3,8,4,10,7,1,9,1,5,7,1,1,7,4},value[41]={0,8,1,5,9,5,6,8,2,3,7,5,4,3,7,6,7,9,3,10,5,2,4,5,2,9,5,8,10,2,9,6,3,7,3,9,6,10,1,2,9},dp[41][51];
bool rec[41][51];
vector<int>vec;
int main(void){
for(register int i=1;i<=40;i++)
for(register int j=1;j<=50;j++)
if(j<weight[i])
dp[i][j]=dp[i-1][j];
else if(value[i]+dp[i-1][j-weight[i]]>dp[i-1][j])
dp[i][j]=value[i]+dp[i-1][j-weight[i]],
rec[i][j]=true;
else
dp[i][j]=dp[i-1][j];
for(register int i=40,j=50;i>0;i--)
if(rec[i][j]==true){
vec.push_back(i);
j-=weight[i];
};
sort(vec.begin(),vec.end());
for(vector<int>::iterator it=vec.begin();it!=vec.end();it++)
printf("%d ",(*it)-1);
return 0;
};

[CISCN 2023 初赛]babyRE

Scratch逆向都出来了,简单算法:

1
2
3
4
5
res=[102,10,13,6,28,74,3,1,3,7,85,0,4,75,20,92,92,8,28,25,81,83,7,28,76,88,9,0,29,73,0,86,4,87,87,82,84,85,4,85,87,30]
for i in range(1,len(res)):
res[i]^=res[i-1]
for i in range(len(res)):
print(chr(res[i]),end='')

[MoeCTF 2021]PEPEPE

脑洞题,给了个加密程序main.exe,又给了个加密文件file。file其实是个.exe经过加密后的,现在要把file_org文件搞出来。

切入点就在DOS_STUB是固定的,写个脚本解出输入的解密密钥,其中取反的逆运算是^0xFF

1
2
3
4
org1=b'This program cannot be run in DOS mode'
enc1=[0xDE,0xB6,0xE4,0xE9,0xA9,0xEA,0xFF,0xF9,0xFD,0xFF,0xE9,0xFB,0xB3,0xF0,0xF2,0xF8,0xFA,0xF5,0xF2,0xB0,0xE8,0xBB,0xAD,0xE8,0xFC,0xF4,0xAD,0xFF,0xF4,0xAD,0xCC,0xD9,0xC0,0xB3,0xFE,0xF9,0xF0,0xFF]
for i in range(len(enc1)):
print(chr(enc1[i]^0xFF^org1[i]),end='')

发现是循环的“reverierwilllikeyou!”,解出来file_org:

1
2
3
4
5
6
7
8
key=b'reverierwilllikeyou!'
f1=open('./file',"rb")
f2=open("./file_org","wb")
orgdata=f1.read()
tmpdata=[0]*len(orgdata)
for i in range(len(orgdata)):
tmpdata[i]=orgdata[i]^0xFF^key[i%len(key)]
f2.write(bytes(tmpdata))

运行就是了。

[zer0pts 2020]easy strcmp

被坑了,这里是QWORD字符串数值相加。如果拆成一个字节一个字节的话,当进位时将出错。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <cstdio>
using namespace std;
unsigned long long keys[5] = {
0x0000000000000000, 0x410A4335494A0942, 0x0B0EF2F50BE619F0, 0x4F0A3A064A35282B,
0x0000000000000000
};
unsigned char enc[]="zer0pts{********CENSORED********}";
int main(void){
for(register int i=0;i<5;i++)
*((unsigned long long*)enc+i)+=keys[i];
printf("%s",enc);
return 0;
};

[HNCTF 2022 Week1]CrackMe

断点下在lstrcmpA处得到的假的序列号,必须步过到ExitProcess才行。看起来好像是怎么HOOK的函数,但具体没看懂。

[LitCTF 2023]程序和人有一个能跑就行了

异常处理而已。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import re
import base64
def rc4_decrypt(ciphertext,key):
S=list(range(256))
j=0
res=[]
for i in range(256):
j=(j+S[i]+key[i%len(key)])%256
S[i],S[j]=S[j],S[i]
i=j=0
for char in ciphertext:
i=(i+1)%256
j=(j+S[i])%256
S[i],S[j]=S[j],S[i]
res.append(char^S[(S[i]+S[j])%256])
return bytes(res)
data_list=[0x8D,0x6C,0x85,0x76,0x32,0x72,0x0B7,0x43,0x85,0x7B,0x85,0x0DE,0x0C1,0x0FB,0x2E,0x64,0x7,0x0C8,0x5F,0x9A,0x35,0x18,0x0AD,0x0B5,0x15,0x92,0x0BE,0x1B,0x88]
key='litctf'
key_list=[ord(c) for c in key]
flag=rc4_decrypt(data_list,key_list)
print(flag)