1
2
3
4 :(scenario pack_immediate_constants)
5 == 0x1
6
7
8
9 bb 0x2a/imm32
10 +transform: packing instruction 'bb 0x2a/imm32'
11 +transform: instruction after packing: 'bb 2a 00 00 00'
12 +run: copy imm32 0x0000002a to EBX
13
14 :(scenario pack_disp8)
15 == 0x1
16 74 2/disp8
17 +transform: packing instruction '74 2/disp8'
18 +transform: instruction after packing: '74 02'
19
20 :(scenarios transform)
21 :(scenario pack_disp8_negative)
22 == 0x1
23
24 74 -1/disp8
25 +transform: packing instruction '74 -1/disp8'
26 +transform: instruction after packing: '74 ff'
27 :(scenarios run)
28
29 :(scenario pack_modrm_imm32)
30 == 0x1
31
32
33
34 81 0/add/subop 3/mod/direct 3/ebx/rm32 1/imm32
35 +transform: packing instruction '81 0/add/subop 3/mod/direct 3/ebx/rm32 1/imm32'
36 +transform: instruction after packing: '81 c3 01 00 00 00'
37
38 :(scenario pack_imm32_large)
39 == 0x1
40 b9 0x080490a7/imm32
41 +transform: packing instruction 'b9 0x080490a7/imm32'
42 +transform: instruction after packing: 'b9 a7 90 04 08'
43
44 :(before "End Transforms")
45 Transform.push_back(pack_operands);
46
47 :(code)
48 void pack_operands(program& p) {
49 trace(99, "transform") << "-- pack operands" << end();
50 if (p.segments.empty()) return;
51 segment& code = p.segments.at(0);
52 for (int i = 0; i < SIZE(code.lines); ++i) {
53 line& inst = code.lines.at(i);
54 if (all_hex_bytes(inst)) continue;
55 trace(99, "transform") << "packing instruction '" << to_string(inst) << "'" << end();
56 pack_operands(inst);
57 trace(99, "transform") << "instruction after packing: '" << to_string(inst.words) << "'" << end();
58 }
59 }
60
61 void pack_operands(line& inst) {
62 line new_inst;
63 add_opcodes(inst, new_inst);
64 add_modrm_byte(inst, new_inst);
65 add_sib_byte(inst, new_inst);
66 add_disp_bytes(inst, new_inst);
67 add_imm_bytes(inst, new_inst);
68 inst.words.swap(new_inst.words);
69 }
70
71 void add_opcodes(const line& in, line& out) {
72 out.words.push_back(in.words.at(0));
73 if (in.words.at(0).data == "0f" || in.words.at(0).data == "f3")
74 out.words.push_back(in.words.at(1));
75 if (in.words.at(0).data == "f3" && in.words.at(1).data == "0f")
76 out.words.push_back(in.words.at(2));
77 }
78
79 void add_modrm_byte(const line& in, line& out) {
80 uint8_t mod=0, reg_subop=0, rm32=0;
81 bool emit = false;
82 for (int i = 0; i < SIZE(in.words); ++i) {
83 const word& curr = in.words.at(i);
84 if (has_metadata(curr, "mod")) {
85 mod = hex_byte(curr.data);
86 emit = true;
87 }
88 else if (has_metadata(curr, "rm32")) {
89 rm32 = hex_byte(curr.data);
90 emit = true;
91 }
92 else if (has_metadata(curr, "r32")) {
93 reg_subop = hex_byte(curr.data);
94 emit = true;
95 }
96 else if (has_metadata(curr, "subop")) {
97 reg_subop = hex_byte(curr.data);
98 emit = true;
99 }
100 }
101 if (emit)
102 out.words.push_back(hex_byte_text((mod << 6) | (reg_subop << 3) | rm32));
103 }
104
105 void add_sib_byte(const line& in, line& out) {
106 uint8_t scale=0, index=0, base=0;
107 bool emit = false;
108 for (int i = 0; i < SIZE(in.words); ++i) {
109 const word& curr = in.words.at(i);
110 if (has_metadata(curr, "scale")) {
111 scale = hex_byte(curr.data);
112 emit = true;
113 }
114 else if (has_metadata(curr, "index")) {
115 index = hex_byte(curr.data);
116 emit = true;
117 }
118 else if (has_metadata(curr, "base")) {
119 base = hex_byte(curr.data);
120 emit = true;
121 }
122 }
123 if (emit)
124 out.words.push_back(hex_byte_text((scale << 6) | (index << 3) | base));
125 }
126
127 void add_disp_bytes(const line& in, line& out) {
128 for (int i = 0; i < SIZE(in.words); ++i) {
129 const word& curr = in.words.at(i);
130 if (has_metadata(curr, "disp8"))
131 emit_hex_bytes(out, curr, 1);
132 if (has_metadata(curr, "disp16"))
133 emit_hex_bytes(out, curr, 2);
134 else if (has_metadata(curr, "disp32"))
135 emit_hex_bytes(out, curr, 4);
136 }
137 }
138
139 void add_imm_bytes(const line& in, line& out) {
140 for (int i = 0; i < SIZE(in.words); ++i) {
141 const word& curr = in.words.at(i);
142 if (has_metadata(curr, "imm8"))
143 emit_hex_bytes(out, curr, 1);
144 else if (has_metadata(curr, "imm32"))
145 emit_hex_bytes(out, curr, 4);
146 }
147 }
148
149 void emit_hex_bytes(line& out, const word& w, int num) {
150 assert(num <= 4);
151 if (!is_hex_int(w.data)) {
152 out.words.push_back(w);
153 return;
154 }
155 emit_hex_bytes(out, static_cast<uint32_t>(parse_int(w.data)), num);
156 }
157
158 void emit_hex_bytes(line& out, uint32_t val, int num) {
159 assert(num <= 4);
160 for (int i = 0; i < num; ++i) {
161 out.words.push_back(hex_byte_text(val & 0xff));
162 val = val >> 8;
163 }
164 }
165
166 word hex_byte_text(uint8_t val) {
167 ostringstream out;
168 out << HEXBYTE << NUM(val);
169 word result;
170 result.data = out.str();
171 result.original = out.str()+"/auto";
172 return result;
173 }
174
175 string to_string(const vector<word>& in) {
176 ostringstream out;
177 for (int i = 0; i < SIZE(in); ++i) {
178 if (i > 0) out << ' ';
179 out << in.at(i).data;
180 }
181 return out.str();
182 }
183
184 :(scenario pack_immediate_constants_hex)
185 == 0x1
186
187
188
189 bb 0x2a/imm32
190 +transform: packing instruction 'bb 0x2a/imm32'
191 +transform: instruction after packing: 'bb 2a 00 00 00'
192 +run: copy imm32 0x0000002a to EBX
193
194 :(scenarios transform)
195 :(scenario pack_silently_ignores_non_hex)
196 == 0x1
197
198
199
200 bb foo/imm32
201 +transform: packing instruction 'bb foo/imm32'
202
203 +transform: instruction after packing: 'bb foo'
204 $error: 0
205 :(scenarios run)