├── .gitignore
├── .gitmodules
├── README.md
├── aarch64-softmmu
├── aarch64-softmmu.vcxproj
├── aarch64-softmmu.vcxproj.filters
└── aarch64-softmmu.vcxproj.user
├── aarch64eb-softmmu
├── aarch64eb-softmmu.vcxproj
├── aarch64eb-softmmu.vcxproj.filters
└── aarch64eb-softmmu.vcxproj.user
├── arm-softmmu
├── arm-softmmu.vcxproj
├── arm-softmmu.vcxproj.filters
└── arm-softmmu.vcxproj.user
├── armeb-softmmu
├── armeb-softmmu.vcxproj
├── armeb-softmmu.vcxproj.filters
└── armeb-softmmu.vcxproj.user
├── asm-trainer.sln
├── asm-trainer
├── aarch32asm.cpp
├── aarch32asm.h
├── aarch32emu.cpp
├── aarch32emu.h
├── aarch64asm.cpp
├── aarch64asm.h
├── aarch64emu.cpp
├── aarch64emu.h
├── allocator.cpp
├── allocator.h
├── asm-trainer.cpp
├── asm-trainer.vcxproj
├── asm-trainer.vcxproj.filters
├── asm-trainer.vcxproj.user
├── assembler.h
├── emu.h
├── exercise.h
├── math_exercises.cpp
├── math_exercises.h
├── pch.cpp
├── pch.h
├── syscall.cpp
├── syscall.h
├── util.h
├── x64asm.cpp
├── x64asm.h
├── x64emu.cpp
├── x64emu.h
├── x86asm.cpp
├── x86asm.h
├── x86emu.cpp
└── x86emu.h
├── examples
├── aarch32.s
├── aarch64.s
├── simplexor-aarch32.s
├── simplexor-aarch64.s
├── simplexor-x64.s
├── simplexor-x86.s
├── x64-mem-mapped.s
├── x64.s
└── x86.s
├── unicorn_lib
├── unicorn_lib.vcxproj
├── unicorn_lib.vcxproj.filters
└── unicorn_lib.vcxproj.user
└── x86_64-softmmu
├── x86_64-softmmu.vcxproj
├── x86_64-softmmu.vcxproj.filters
└── x86_64-softmmu.vcxproj.user
/.gitignore:
--------------------------------------------------------------------------------
1 | x64
2 | .vs
3 | .VC.db
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "ext/keystone"]
2 | path = ext/keystone
3 | url = https://github.com/keystone-engine/keystone.git
4 | [submodule "ext/unicorn"]
5 | path = ext/unicorn
6 | url = https://github.com/unicorn-engine/unicorn.git
7 | [submodule "ext/cxxopts"]
8 | path = ext/cxxopts
9 | url = https://github.com/jarro2783/cxxopts.git
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## asm-trainer
2 |
3 | Archs supported:
4 | - aarch32 (ARMv7)
5 | - aarch64 (ARMv8)
6 | - i386
7 | - amd64
--------------------------------------------------------------------------------
/aarch64-softmmu/aarch64-softmmu.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
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 | true
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 | 15.0
77 | {6276467D-7694-4F63-8F5B-BB8C285519FD}
78 | Win32Proj
79 | aarch64softmmu
80 | 10.0.17763.0
81 |
82 |
83 |
84 | StaticLibrary
85 | true
86 | v141
87 | Unicode
88 |
89 |
90 | StaticLibrary
91 | false
92 | v141
93 | true
94 | Unicode
95 |
96 |
97 | StaticLibrary
98 | true
99 | v141
100 | Unicode
101 |
102 |
103 | StaticLibrary
104 | false
105 | v141
106 | true
107 | Unicode
108 | false
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | false
130 |
131 |
132 | true
133 |
134 |
135 | true
136 |
137 |
138 | false
139 |
140 |
141 |
142 | NotUsing
143 | Level3
144 | MaxSpeed
145 | true
146 | true
147 |
148 |
149 | WIN32;NDEBUG;_LIB;__x86_64__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN
150 | false
151 | $(SolutionDir)ext/unicorn/include;$(SolutionDir)ext/unicorn/qemu;$(SolutionDir)ext/unicorn/qemu/include;$(SolutionDir)ext/unicorn/qemu/tcg;$(SolutionDir)ext/unicorn/qemu/tcg/i386;$(SolutionDir)ext/unicorn/qemu/target-arm;$(SolutionDir)ext/unicorn/msvc/unicorn;$(SolutionDir)ext/unicorn/msvc/unicorn/aarch64-softmmu;%(AdditionalIncludeDirectories)
152 | None
153 | false
154 | false
155 | MultiThreaded
156 | aarch64.h
157 |
158 |
159 | Windows
160 | true
161 | true
162 | true
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | Use
171 | Level3
172 | Disabled
173 | true
174 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
175 | true
176 |
177 |
178 | Windows
179 | true
180 |
181 |
182 |
183 |
184 | Use
185 | Level3
186 | Disabled
187 | true
188 | _DEBUG;_LIB;%(PreprocessorDefinitions)
189 | true
190 |
191 |
192 | Windows
193 | true
194 |
195 |
196 |
197 |
198 | Use
199 | Level3
200 | MaxSpeed
201 | true
202 | true
203 | true
204 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
205 | true
206 |
207 |
208 | Windows
209 | true
210 | true
211 | true
212 |
213 |
214 |
215 |
216 |
217 |
--------------------------------------------------------------------------------
/aarch64-softmmu/aarch64-softmmu.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {88113189-817d-4915-9a24-b7b66c851f37}
6 |
7 |
8 | {8a332321-f8a0-4356-a9c5-a4dfb0b2d90b}
9 |
10 |
11 | {2d0d2d01-4ada-4ac4-b8e6-06fd34224f7b}
12 |
13 |
14 | {62dbbe2b-2869-4005-8a64-c48cf51b7e50}
15 |
16 |
17 | {2a2fe408-b65c-43b5-9b09-57c13715666e}
18 |
19 |
20 | {6a458ee9-dd8f-4925-a866-e46494ed52f8}
21 |
22 |
23 |
24 |
25 | fpu
26 |
27 |
28 | hw\arm
29 |
30 |
31 | hw\arm
32 |
33 |
34 | target-arm
35 |
36 |
37 | target-arm
38 |
39 |
40 | target-arm
41 |
42 |
43 | target-arm
44 |
45 |
46 | target-arm
47 |
48 |
49 | target-arm
50 |
51 |
52 | target-arm
53 |
54 |
55 | target-arm
56 |
57 |
58 | target-arm
59 |
60 |
61 | target-arm
62 |
63 |
64 | target-arm
65 |
66 |
67 | target-arm
68 |
69 |
70 | tcg\i386
71 |
72 |
73 | tcg
74 |
75 |
76 | tcg
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | fpu
90 |
91 |
92 | fpu
93 |
94 |
95 | target-arm
96 |
97 |
98 | target-arm
99 |
100 |
101 | target-arm
102 |
103 |
104 | target-arm
105 |
106 |
107 | target-arm
108 |
109 |
110 | target-arm
111 |
112 |
113 | target-arm
114 |
115 |
116 | target-arm
117 |
118 |
119 | target-arm
120 |
121 |
122 | target-arm
123 |
124 |
125 | tcg\i386
126 |
127 |
128 | tcg
129 |
130 |
131 | tcg
132 |
133 |
134 | tcg
135 |
136 |
137 | tcg
138 |
139 |
140 | tcg
141 |
142 |
143 | tcg
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/aarch64-softmmu/aarch64-softmmu.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/aarch64eb-softmmu/aarch64eb-softmmu.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
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 | true
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 | 15.0
77 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}
78 | Win32Proj
79 | aarch64ebsoftmmu
80 | 10.0.17763.0
81 |
82 |
83 |
84 | StaticLibrary
85 | true
86 | v141
87 | Unicode
88 |
89 |
90 | StaticLibrary
91 | false
92 | v141
93 | true
94 | Unicode
95 |
96 |
97 | StaticLibrary
98 | true
99 | v141
100 | Unicode
101 |
102 |
103 | StaticLibrary
104 | false
105 | v141
106 | true
107 | Unicode
108 | false
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | false
130 |
131 |
132 | true
133 |
134 |
135 | true
136 |
137 |
138 | false
139 |
140 |
141 |
142 | NotUsing
143 | Level3
144 | MaxSpeed
145 | true
146 | true
147 |
148 |
149 | WIN32;NDEBUG;_LIB;__x86_64__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN
150 | false
151 | $(SolutionDir)ext/unicorn/include;$(SolutionDir)ext/unicorn/qemu;$(SolutionDir)ext/unicorn/qemu/include;$(SolutionDir)ext/unicorn/qemu/tcg;$(SolutionDir)ext/unicorn/qemu/tcg/i386;$(SolutionDir)ext/unicorn/qemu/target-arm;$(SolutionDir)ext/unicorn/msvc/unicorn;$(SolutionDir)ext/unicorn/msvc/unicorn/aarch64eb-softmmu;%(AdditionalIncludeDirectories)
152 | None
153 | false
154 | false
155 | MultiThreaded
156 | aarch64eb.h
157 |
158 |
159 | Windows
160 | true
161 | true
162 | true
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | Use
171 | Level3
172 | Disabled
173 | true
174 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
175 | true
176 |
177 |
178 | Windows
179 | true
180 |
181 |
182 |
183 |
184 | Use
185 | Level3
186 | Disabled
187 | true
188 | _DEBUG;_LIB;%(PreprocessorDefinitions)
189 | true
190 |
191 |
192 | Windows
193 | true
194 |
195 |
196 |
197 |
198 | Use
199 | Level3
200 | MaxSpeed
201 | true
202 | true
203 | true
204 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
205 | true
206 |
207 |
208 | Windows
209 | true
210 | true
211 | true
212 |
213 |
214 |
215 |
216 |
217 |
--------------------------------------------------------------------------------
/aarch64eb-softmmu/aarch64eb-softmmu.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {07f3933f-fd0a-4898-86c9-53828f0afbc0}
6 |
7 |
8 | {f4e7fd5b-2a82-4394-ac76-f7508a396835}
9 |
10 |
11 | {2d0c5c58-0ac0-4c22-a336-c9802f66e155}
12 |
13 |
14 | {0888f30e-969a-4f62-9cca-92432d93d63c}
15 |
16 |
17 | {2220382a-02b0-4a32-afc0-966870e674f6}
18 |
19 |
20 | {c3e69bf1-85ba-4b03-bb2d-8a3589ac893d}
21 |
22 |
23 |
24 |
25 | fpu
26 |
27 |
28 | hw\arm
29 |
30 |
31 | hw\arm
32 |
33 |
34 | target-arm
35 |
36 |
37 | target-arm
38 |
39 |
40 | target-arm
41 |
42 |
43 | target-arm
44 |
45 |
46 | target-arm
47 |
48 |
49 | target-arm
50 |
51 |
52 | target-arm
53 |
54 |
55 | target-arm
56 |
57 |
58 | target-arm
59 |
60 |
61 | target-arm
62 |
63 |
64 | target-arm
65 |
66 |
67 | target-arm
68 |
69 |
70 | tcg\i386
71 |
72 |
73 | tcg
74 |
75 |
76 | tcg
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | fpu
90 |
91 |
92 | fpu
93 |
94 |
95 | target-arm
96 |
97 |
98 | target-arm
99 |
100 |
101 | target-arm
102 |
103 |
104 | target-arm
105 |
106 |
107 | target-arm
108 |
109 |
110 | target-arm
111 |
112 |
113 | target-arm
114 |
115 |
116 | target-arm
117 |
118 |
119 | target-arm
120 |
121 |
122 | target-arm
123 |
124 |
125 | tcg\i386
126 |
127 |
128 | tcg
129 |
130 |
131 | tcg
132 |
133 |
134 | tcg
135 |
136 |
137 | tcg
138 |
139 |
140 | tcg
141 |
142 |
143 | tcg
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/aarch64eb-softmmu/aarch64eb-softmmu.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/arm-softmmu/arm-softmmu.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | true
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 | 15.0
73 | {D57FFF76-28B6-4265-81E5-689AE07DF310}
74 | Win32Proj
75 | armsoftmmu
76 | 10.0.17763.0
77 |
78 |
79 |
80 | StaticLibrary
81 | true
82 | v141
83 | Unicode
84 |
85 |
86 | StaticLibrary
87 | false
88 | v141
89 | true
90 | Unicode
91 |
92 |
93 | StaticLibrary
94 | true
95 | v141
96 | Unicode
97 |
98 |
99 | StaticLibrary
100 | false
101 | v141
102 | true
103 | Unicode
104 | false
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | false
126 |
127 |
128 | true
129 |
130 |
131 | true
132 |
133 |
134 | false
135 |
136 |
137 |
138 |
139 |
140 | Level3
141 | Disabled
142 | true
143 | false
144 |
145 |
146 | WIN32;NDEBUG;_LIB;__x86_64__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN
147 | false
148 | None
149 | $(SolutionDir)ext/unicorn/include;$(SolutionDir)ext/unicorn/qemu;$(SolutionDir)ext/unicorn/qemu/include;$(SolutionDir)ext/unicorn/qemu/tcg;$(SolutionDir)ext/unicorn/qemu/tcg/i386;$(SolutionDir)ext/unicorn/qemu/target-arm;$(SolutionDir)ext/unicorn/msvc/unicorn;$(SolutionDir)ext/unicorn/msvc/unicorn/arm-softmmu;%(AdditionalIncludeDirectories)
150 | false
151 | false
152 | false
153 | MultiThreaded
154 | arm.h
155 |
156 |
157 | Windows
158 | true
159 | true
160 | true
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | Use
169 | Level3
170 | Disabled
171 | true
172 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
173 | true
174 |
175 |
176 | Windows
177 | true
178 |
179 |
180 |
181 |
182 | Use
183 | Level3
184 | Disabled
185 | true
186 | _DEBUG;_LIB;%(PreprocessorDefinitions)
187 | true
188 |
189 |
190 | Windows
191 | true
192 |
193 |
194 |
195 |
196 | Use
197 | Level3
198 | MaxSpeed
199 | true
200 | true
201 | true
202 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
203 | true
204 |
205 |
206 | Windows
207 | true
208 | true
209 | true
210 |
211 |
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/arm-softmmu/arm-softmmu.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {adab4322-6b0e-48f6-9c73-cdc59458ab8f}
6 |
7 |
8 | {7eba51ec-ecb4-4454-95cf-1ce0904a1a5c}
9 |
10 |
11 | {177be483-368d-4c4f-a443-f28d94296e33}
12 |
13 |
14 | {7245f661-eeb5-4086-a3d1-18051d1df2f8}
15 |
16 |
17 | {33ea3e70-c1b1-4f3d-b87d-a2fbdab3b963}
18 |
19 |
20 | {ae963627-0d38-4a07-8538-e5ec9e1a3a64}
21 |
22 |
23 |
24 |
25 | fpu
26 |
27 |
28 | hw\arm
29 |
30 |
31 | hw\arm
32 |
33 |
34 | tcg\i386
35 |
36 |
37 | tcg
38 |
39 |
40 | tcg
41 |
42 |
43 | target-arm
44 |
45 |
46 | target-arm
47 |
48 |
49 | target-arm
50 |
51 |
52 | target-arm
53 |
54 |
55 | target-arm
56 |
57 |
58 | target-arm
59 |
60 |
61 | target-arm
62 |
63 |
64 | target-arm
65 |
66 |
67 | target-arm
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | fpu
81 |
82 |
83 | fpu
84 |
85 |
86 | tcg\i386
87 |
88 |
89 | tcg
90 |
91 |
92 | tcg
93 |
94 |
95 | tcg
96 |
97 |
98 | tcg
99 |
100 |
101 | tcg
102 |
103 |
104 | tcg
105 |
106 |
107 | target-arm
108 |
109 |
110 | target-arm
111 |
112 |
113 | target-arm
114 |
115 |
116 | target-arm
117 |
118 |
119 | target-arm
120 |
121 |
122 | target-arm
123 |
124 |
125 | target-arm
126 |
127 |
128 | target-arm
129 |
130 |
131 | target-arm
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/arm-softmmu/arm-softmmu.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/armeb-softmmu/armeb-softmmu.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | true
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 | 15.0
73 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}
74 | Win32Proj
75 | armebsoftmmu
76 | 10.0.17763.0
77 |
78 |
79 |
80 | StaticLibrary
81 | true
82 | v141
83 | Unicode
84 |
85 |
86 | StaticLibrary
87 | false
88 | v141
89 | true
90 | Unicode
91 |
92 |
93 | StaticLibrary
94 | true
95 | v141
96 | Unicode
97 |
98 |
99 | StaticLibrary
100 | false
101 | v141
102 | true
103 | Unicode
104 | false
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | false
126 |
127 |
128 | true
129 |
130 |
131 | true
132 |
133 |
134 | false
135 |
136 |
137 |
138 |
139 |
140 | Level3
141 | MaxSpeed
142 | true
143 | true
144 |
145 |
146 | WIN32;NDEBUG;_LIB;__x86_64__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN
147 | false
148 | None
149 | false
150 | false
151 | false
152 | MultiThreaded
153 | armeb.h
154 | $(SolutionDir)ext/unicorn/include;$(SolutionDir)ext/unicorn/qemu;$(SolutionDir)ext/unicorn/qemu/include;$(SolutionDir)ext/unicorn/qemu/tcg;$(SolutionDir)ext/unicorn/qemu/tcg/i386;$(SolutionDir)ext/unicorn/qemu/target-arm;$(SolutionDir)ext/unicorn/msvc/unicorn;$(SolutionDir)ext/unicorn/msvc/unicorn/armeb-softmmu;%(AdditionalIncludeDirectories)
155 |
156 |
157 | Windows
158 | true
159 | true
160 | true
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 | Use
169 | Level3
170 | Disabled
171 | true
172 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
173 | true
174 |
175 |
176 | Windows
177 | true
178 |
179 |
180 |
181 |
182 | Use
183 | Level3
184 | Disabled
185 | true
186 | _DEBUG;_LIB;%(PreprocessorDefinitions)
187 | true
188 |
189 |
190 | Windows
191 | true
192 |
193 |
194 |
195 |
196 | Use
197 | Level3
198 | MaxSpeed
199 | true
200 | true
201 | true
202 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
203 | true
204 |
205 |
206 | Windows
207 | true
208 | true
209 | true
210 |
211 |
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/armeb-softmmu/armeb-softmmu.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {1d44611d-e86c-45a7-b919-d34fe6c1965d}
6 |
7 |
8 | {2f557728-f12a-4f95-8a45-65e73c7725f4}
9 |
10 |
11 | {4914b85d-bc9f-457c-b1bf-b7e23c567be7}
12 |
13 |
14 | {c4bec68f-0ac8-46eb-8a9b-eccd55aa87ec}
15 |
16 |
17 | {f1257bd2-e202-41e8-b7b5-7fe4ea1d069e}
18 |
19 |
20 | {539b5ea8-7fac-4831-b6c3-e6b5051c92f9}
21 |
22 |
23 |
24 |
25 | fpu
26 |
27 |
28 | hw\arm
29 |
30 |
31 | hw\arm
32 |
33 |
34 | tcg
35 |
36 |
37 | tcg
38 |
39 |
40 | target-arm
41 |
42 |
43 | target-arm
44 |
45 |
46 | target-arm
47 |
48 |
49 | target-arm
50 |
51 |
52 | target-arm
53 |
54 |
55 | target-arm
56 |
57 |
58 | target-arm
59 |
60 |
61 | target-arm
62 |
63 |
64 | target-arm
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | tcg\i386
76 |
77 |
78 |
79 |
80 | fpu
81 |
82 |
83 | fpu
84 |
85 |
86 | tcg
87 |
88 |
89 | tcg
90 |
91 |
92 | tcg
93 |
94 |
95 | tcg
96 |
97 |
98 | tcg
99 |
100 |
101 | tcg
102 |
103 |
104 | tcg\i386
105 |
106 |
107 | target-arm
108 |
109 |
110 | target-arm
111 |
112 |
113 | target-arm
114 |
115 |
116 | target-arm
117 |
118 |
119 | target-arm
120 |
121 |
122 | target-arm
123 |
124 |
125 | target-arm
126 |
127 |
128 | target-arm
129 |
130 |
131 | target-arm
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/armeb-softmmu/armeb-softmmu.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/asm-trainer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28306.52
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asm-trainer", "asm-trainer\asm-trainer.vcxproj", "{1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}"
7 | ProjectSection(ProjectDependencies) = postProject
8 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558} = {8C3AD934-3C92-4CEC-B06C-68697E9FD558}
9 | {D57FFF76-28B6-4265-81E5-689AE07DF310} = {D57FFF76-28B6-4265-81E5-689AE07DF310}
10 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D} = {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}
11 | {6276467D-7694-4F63-8F5B-BB8C285519FD} = {6276467D-7694-4F63-8F5B-BB8C285519FD}
12 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86} = {0970ED91-BEC1-4070-83D7-F4A068DFFA86}
13 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B} = {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}
14 | EndProjectSection
15 | EndProject
16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicorn_lib", "unicorn_lib\unicorn_lib.vcxproj", "{0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}"
17 | ProjectSection(ProjectDependencies) = postProject
18 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558} = {8C3AD934-3C92-4CEC-B06C-68697E9FD558}
19 | {D57FFF76-28B6-4265-81E5-689AE07DF310} = {D57FFF76-28B6-4265-81E5-689AE07DF310}
20 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D} = {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}
21 | {6276467D-7694-4F63-8F5B-BB8C285519FD} = {6276467D-7694-4F63-8F5B-BB8C285519FD}
22 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86} = {0970ED91-BEC1-4070-83D7-F4A068DFFA86}
23 | EndProjectSection
24 | EndProject
25 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "softmmu", "softmmu", "{B463E5E3-FF8C-44D2-A8E0-2730873A7379}"
26 | EndProject
27 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aarch64-softmmu", "aarch64-softmmu\aarch64-softmmu.vcxproj", "{6276467D-7694-4F63-8F5B-BB8C285519FD}"
28 | EndProject
29 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aarch64eb-softmmu", "aarch64eb-softmmu\aarch64eb-softmmu.vcxproj", "{0970ED91-BEC1-4070-83D7-F4A068DFFA86}"
30 | EndProject
31 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "armeb-softmmu", "armeb-softmmu\armeb-softmmu.vcxproj", "{DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}"
32 | EndProject
33 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "arm-softmmu", "arm-softmmu\arm-softmmu.vcxproj", "{D57FFF76-28B6-4265-81E5-689AE07DF310}"
34 | EndProject
35 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "x86_64-softmmu", "x86_64-softmmu\x86_64-softmmu.vcxproj", "{8C3AD934-3C92-4CEC-B06C-68697E9FD558}"
36 | EndProject
37 | Global
38 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
39 | Debug|x64 = Debug|x64
40 | Debug|x86 = Debug|x86
41 | Release|x64 = Release|x64
42 | Release|x86 = Release|x86
43 | EndGlobalSection
44 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
45 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Debug|x64.ActiveCfg = Debug|x64
46 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Debug|x64.Build.0 = Debug|x64
47 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Debug|x86.ActiveCfg = Debug|Win32
48 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Debug|x86.Build.0 = Debug|Win32
49 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Release|x64.ActiveCfg = Release|x64
50 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Release|x64.Build.0 = Release|x64
51 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Release|x86.ActiveCfg = Release|Win32
52 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}.Release|x86.Build.0 = Release|Win32
53 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Debug|x64.ActiveCfg = Debug|x64
54 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Debug|x64.Build.0 = Debug|x64
55 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Debug|x86.ActiveCfg = Debug|Win32
56 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Debug|x86.Build.0 = Debug|Win32
57 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Release|x64.ActiveCfg = Release|x64
58 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Release|x64.Build.0 = Release|x64
59 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Release|x86.ActiveCfg = Release|Win32
60 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B}.Release|x86.Build.0 = Release|Win32
61 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Debug|x64.ActiveCfg = Debug|x64
62 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Debug|x64.Build.0 = Debug|x64
63 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Debug|x86.ActiveCfg = Debug|Win32
64 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Debug|x86.Build.0 = Debug|Win32
65 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Release|x64.ActiveCfg = Release|x64
66 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Release|x64.Build.0 = Release|x64
67 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Release|x86.ActiveCfg = Release|Win32
68 | {6276467D-7694-4F63-8F5B-BB8C285519FD}.Release|x86.Build.0 = Release|Win32
69 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Debug|x64.ActiveCfg = Debug|x64
70 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Debug|x64.Build.0 = Debug|x64
71 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Debug|x86.ActiveCfg = Debug|Win32
72 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Debug|x86.Build.0 = Debug|Win32
73 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Release|x64.ActiveCfg = Release|x64
74 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Release|x64.Build.0 = Release|x64
75 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Release|x86.ActiveCfg = Release|Win32
76 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86}.Release|x86.Build.0 = Release|Win32
77 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Debug|x64.ActiveCfg = Debug|x64
78 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Debug|x64.Build.0 = Debug|x64
79 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Debug|x86.ActiveCfg = Debug|Win32
80 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Debug|x86.Build.0 = Debug|Win32
81 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Release|x64.ActiveCfg = Release|x64
82 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Release|x64.Build.0 = Release|x64
83 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Release|x86.ActiveCfg = Release|Win32
84 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D}.Release|x86.Build.0 = Release|Win32
85 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Debug|x64.ActiveCfg = Debug|x64
86 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Debug|x64.Build.0 = Debug|x64
87 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Debug|x86.ActiveCfg = Debug|Win32
88 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Debug|x86.Build.0 = Debug|Win32
89 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Release|x64.ActiveCfg = Release|x64
90 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Release|x64.Build.0 = Release|x64
91 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Release|x86.ActiveCfg = Release|Win32
92 | {D57FFF76-28B6-4265-81E5-689AE07DF310}.Release|x86.Build.0 = Release|Win32
93 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Debug|x64.ActiveCfg = Debug|x64
94 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Debug|x64.Build.0 = Debug|x64
95 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Debug|x86.ActiveCfg = Debug|Win32
96 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Debug|x86.Build.0 = Debug|Win32
97 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Release|x64.ActiveCfg = Release|x64
98 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Release|x64.Build.0 = Release|x64
99 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Release|x86.ActiveCfg = Release|Win32
100 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558}.Release|x86.Build.0 = Release|Win32
101 | EndGlobalSection
102 | GlobalSection(SolutionProperties) = preSolution
103 | HideSolutionNode = FALSE
104 | EndGlobalSection
105 | GlobalSection(NestedProjects) = preSolution
106 | {6276467D-7694-4F63-8F5B-BB8C285519FD} = {B463E5E3-FF8C-44D2-A8E0-2730873A7379}
107 | {0970ED91-BEC1-4070-83D7-F4A068DFFA86} = {B463E5E3-FF8C-44D2-A8E0-2730873A7379}
108 | {DAD9A27A-EFCA-45B9-AA8D-6D5577EEDB5D} = {B463E5E3-FF8C-44D2-A8E0-2730873A7379}
109 | {D57FFF76-28B6-4265-81E5-689AE07DF310} = {B463E5E3-FF8C-44D2-A8E0-2730873A7379}
110 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558} = {B463E5E3-FF8C-44D2-A8E0-2730873A7379}
111 | EndGlobalSection
112 | GlobalSection(ExtensibilityGlobals) = postSolution
113 | SolutionGuid = {BFDF07B9-A11F-409C-AA1B-37340B8DC8FD}
114 | EndGlobalSection
115 | EndGlobal
116 |
--------------------------------------------------------------------------------
/asm-trainer/aarch32asm.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "keystone/keystone.h"
3 | #include "assembler.h"
4 | #include "aarch32asm.h"
5 |
6 | bool ARM32Assembler::Initialize()
7 | {
8 | ks_err err = ks_open(KS_ARCH_ARM, KS_MODE_ARM, &m_ks);
9 |
10 | if (err != KS_ERR_OK)
11 | {
12 | std::cerr << "[ERROR] Assembly engine returned error [" << ks_strerror(err) << "]" << std::endl;
13 | return false;
14 | }
15 |
16 | return true;
17 | }
18 |
19 | bool ARM32Assembler::Assemble(std::string& assembly, std::vector& encoded)
20 | {
21 | size_t size = 0, count = 0;
22 |
23 | unsigned char* enc = nullptr;
24 |
25 | const int result = ks_asm(m_ks, assembly.c_str(), 0, &enc, &size, &count);
26 |
27 | if (result != 0)
28 | {
29 | const char* errorDescription = ks_strerror(ks_errno(m_ks));
30 |
31 | std::cerr << "[ERROR] Assembly engine ks_asm returned error after executing " << count << " statements (" << errorDescription << ")" << std::endl;
32 | return false;
33 | }
34 |
35 | if (size == 0)
36 | {
37 | std::cerr << "[ERROR] Generated assembly from ks_asm is 0 bytes." << std::endl;
38 | return false;
39 | }
40 |
41 | encoded.resize(size);
42 |
43 | memcpy(encoded.data(), enc, size);
44 |
45 | ks_free(enc);
46 | ks_close(m_ks);
47 |
48 | m_ks = nullptr;
49 |
50 | return true;
51 | }
--------------------------------------------------------------------------------
/asm-trainer/aarch32asm.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class ARM32Assembler : public Assembler
4 | {
5 | public:
6 | virtual bool Initialize() override;
7 | virtual bool Assemble(std::string& assembly, std::vector& encoded) override;
8 | };
--------------------------------------------------------------------------------
/asm-trainer/aarch32emu.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "unicorn/unicorn.h"
3 | #include "allocator.h"
4 | #include "emu.h"
5 | #include "aarch32emu.h"
6 | #include "syscall.h"
7 |
8 | struct SvcCall
9 | {
10 | uint32_t svcNumber : 24; //
11 | uint32_t b1 : 4; // 1 1 1 1
12 | uint32_t cond : 4; //
13 | };
14 | static_assert(sizeof(SvcCall) == sizeof(uint32_t), "Invalid size for SvcCall");
15 |
16 | static void ARM32_InterruptHook(uc_engine* uc, uint32_t number, void* user_data)
17 | {
18 | uint32_t pc;
19 | uc_err err = uc_reg_read(uc, UC_ARM_REG_PC, &pc);
20 |
21 | if (err != UC_ERR_OK)
22 | {
23 | // Don't handle this
24 | return;
25 | }
26 |
27 | SvcCall call_value = { 0 };
28 | err = uc_mem_read(uc, pc - sizeof(SvcCall), &call_value, sizeof(call_value));
29 |
30 | if (err != UC_ERR_OK)
31 | {
32 | return;
33 | }
34 |
35 | // We are NOT handling a (valid) SVC interrupt
36 | if (number != 2 || call_value.b1 != 15)
37 | {
38 | return;
39 | }
40 |
41 | // Just grab a bunch of registers here so we don't have to make a bunch of calls
42 | // Being lazy =)
43 | uint32_t r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
44 |
45 | uc_reg_read(uc, UC_ARM_REG_R0, &r0);
46 | uc_reg_read(uc, UC_ARM_REG_R1, &r1);
47 | uc_reg_read(uc, UC_ARM_REG_R2, &r2);
48 | uc_reg_read(uc, UC_ARM_REG_R3, &r3);
49 | uc_reg_read(uc, UC_ARM_REG_R4, &r4);
50 |
51 | SyscallHandler(uc, user_data, call_value.svcNumber, r0, r1, r2, r3, r4);
52 |
53 | uc_reg_write(uc, UC_ARM_REG_R0, &r0);
54 | uc_reg_write(uc, UC_ARM_REG_R1, &r1);
55 | uc_reg_write(uc, UC_ARM_REG_R2, &r2);
56 | uc_reg_write(uc, UC_ARM_REG_R3, &r3);
57 | uc_reg_write(uc, UC_ARM_REG_R4, &r4);
58 | }
59 |
60 | bool ARM32Emulator::Initialize(void* buffer, size_t size)
61 | {
62 | uc_err err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &m_uc);
63 |
64 | if (err)
65 | {
66 | std::cerr << "[ERROR] Emulator uc_open failed with error [" << uc_strerror(err) << "]" << std::endl;
67 |
68 | return false;
69 | }
70 |
71 | m_alloc = new Allocator(m_uc, 4096U);
72 |
73 | if (!m_alloc->Map(buffer, size, nullptr))
74 | {
75 | std::cerr << "[ERROR] Allocator failed to map code." << std::endl;
76 |
77 | return false;
78 | }
79 |
80 | std::cout << "Reserving stack space (" << m_stackSize << ")" << std::endl;
81 |
82 | uint64_t stackAddress = 0;
83 | if (!m_alloc->Allocate(m_stackSize, &stackAddress))
84 | {
85 | std::cerr << "[ERROR] Allocator failed to allocate stack space." << std::endl;
86 |
87 | return false;
88 | }
89 |
90 | std::cout << ">>> Reserved " << std::hex << m_stackSize << std::dec << " bytes of stack space at address " << std::hex << stackAddress << std::dec << std::endl;
91 |
92 | // See: ARM64, i don't think ARM is responsible for similar behavior, but no need to risk it
93 | uint64_t stackSlackSpaceAddress = stackAddress + 32;
94 |
95 | err = uc_reg_write(m_uc, UC_ARM_REG_SP, &stackSlackSpaceAddress);
96 |
97 | if (err)
98 | {
99 | std::cerr << "[ERROR] Emulator uc_reg_write failed with error [" << uc_strerror(err) << "]" << std::endl;
100 |
101 | return false;
102 | }
103 |
104 | uc_hook trace;
105 | err = uc_hook_add(m_uc, &trace, UC_HOOK_INTR, ARM32_InterruptHook, this, 0, -1);
106 |
107 | if (err)
108 | {
109 | std::cerr << "[ERROR] Emulator uc_hook_add failed with error [" << uc_strerror(err) << "]" << std::endl;
110 |
111 | return false;
112 | }
113 |
114 | m_bufferSize = size;
115 |
116 | return true;
117 | }
118 |
119 | bool ARM32Emulator::Emulate()
120 | {
121 | uc_err err = uc_emu_start(m_uc, 0, m_bufferSize, 0, 0);
122 |
123 | //
124 |
125 | if (err)
126 | {
127 | std::cerr << "[ERROR] Emulator uc_emu_start failed with error [" << uc_strerror(err) << "]" << std::endl;
128 | return false;
129 | }
130 |
131 | return true;
132 | }
133 |
134 | template
135 | uc_err ReadRegisterBatch(uc_engine* uc, const int(®isterIds)[N], uint32_t(&values)[N])
136 | {
137 | void* ptrs[N] = { nullptr };
138 |
139 | for (size_t i = 0; i < N; ++i)
140 | {
141 | ptrs[i] = &values[i];
142 | }
143 |
144 | return uc_reg_read_batch(uc, const_cast(registerIds), ptrs, N);
145 | }
146 |
147 | void ARM32Emulator::PrintContext(std::ostream& os)
148 | {
149 | const int regIds[] =
150 | {
151 | UC_ARM_REG_R0,
152 | UC_ARM_REG_R1,
153 | UC_ARM_REG_R2,
154 | UC_ARM_REG_R3,
155 | UC_ARM_REG_R4,
156 | UC_ARM_REG_R5,
157 | UC_ARM_REG_PC,
158 | UC_ARM_REG_FP,
159 | UC_ARM_REG_LR
160 | };
161 |
162 | const char* regNames[] =
163 | {
164 | "R0",
165 | "R1",
166 | "R2",
167 | "R3",
168 | "R4",
169 | "R5",
170 | "PC",
171 | "FP",
172 | "LR"
173 | };
174 |
175 | os << "Context: {" << std::endl;
176 |
177 | constexpr size_t count = sizeof(regIds) / sizeof(int);
178 |
179 | uint32_t values[count] = { 0 };
180 |
181 | uc_err err = ReadRegisterBatch(m_uc, regIds, values);
182 | if (err)
183 | {
184 | os << "\t" << std::endl;
185 | }
186 | else
187 | {
188 | for (size_t i = 0; i < count; i++)
189 | {
190 | os << "\t" << regNames[i] << " = " << values[i] << std::endl;
191 | }
192 | }
193 |
194 | os << "}" << std::endl;
195 | }
196 |
197 | void ARM32Emulator::Close()
198 | {
199 | if (m_uc != nullptr)
200 | uc_close(m_uc);
201 |
202 | m_uc = nullptr;
203 | }
--------------------------------------------------------------------------------
/asm-trainer/aarch32emu.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class ARM32Emulator : public Emulator
4 | {
5 | public:
6 | ARM32Emulator(uint64_t stackSize) : Emulator(), m_bufferSize(0), m_stackSize(stackSize) {}
7 |
8 | bool Initialize(void* buffer, size_t size) override;
9 | bool Emulate() override;
10 | void PrintContext(std::ostream& os) override;
11 | void Close() override;
12 |
13 | private:
14 | uint64_t m_bufferSize;
15 | uint64_t m_stackSize;
16 | };
--------------------------------------------------------------------------------
/asm-trainer/aarch64asm.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "keystone/keystone.h"
3 | #include "assembler.h"
4 | #include "aarch64asm.h"
5 |
6 | bool ARM64Assembler::Initialize()
7 | {
8 | ks_err err = ks_open(KS_ARCH_ARM64, 0, &m_ks);
9 |
10 | if (err != KS_ERR_OK)
11 | {
12 | std::cerr << "[ERROR] Assembly engine returned error [" << ks_strerror(err) << "]" << std::endl;
13 | return false;
14 | }
15 |
16 | return true;
17 | }
18 |
19 | bool ARM64Assembler::Assemble(std::string& assembly, std::vector& encoded)
20 | {
21 | size_t size = 0, count = 0;
22 |
23 | unsigned char* enc = nullptr;
24 |
25 | const int result = ks_asm(m_ks, assembly.c_str(), 0, &enc, &size, &count);
26 |
27 | if (result != 0)
28 | {
29 | const char* errorDescription = ks_strerror(ks_errno(m_ks));
30 |
31 | std::cerr << "[ERROR] Assembly engine ks_asm returned error after executing " << count << " statements (" << errorDescription << ")" << std::endl;
32 | return false;
33 | }
34 |
35 | if (size == 0)
36 | {
37 | std::cerr << "[ERROR] Generated assembly from ks_asm is 0 bytes." << std::endl;
38 | return false;
39 | }
40 |
41 | encoded.resize(size);
42 |
43 | memcpy(encoded.data(), enc, size);
44 |
45 | ks_free(enc);
46 | ks_close(m_ks);
47 |
48 | m_ks = nullptr;
49 |
50 | return true;
51 | }
--------------------------------------------------------------------------------
/asm-trainer/aarch64asm.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class ARM64Assembler : public Assembler
4 | {
5 | public:
6 | virtual bool Initialize() override;
7 | virtual bool Assemble(std::string& assembly, std::vector& encoded) override;
8 | };
--------------------------------------------------------------------------------
/asm-trainer/aarch64emu.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "unicorn/unicorn.h"
3 | #include "allocator.h"
4 | #include "emu.h"
5 | #include "aarch64emu.h"
6 | #include "syscall.h"
7 |
8 | struct SvcCall
9 | {
10 | uint32_t b1 : 1; // 1
11 | uint32_t b2 : 1; // 0
12 | uint32_t b3 : 3; // 0 0 0
13 | uint32_t svcNumber : 16; //
14 | uint32_t b4 : 3; // 0 0 0
15 | uint32_t b5 : 8; // 0 0 1 0 1 0 1 1
16 | };
17 | static_assert(sizeof(SvcCall) == sizeof(uint32_t), "Invalid size for SvcCall");
18 |
19 | static void ARM64_InterruptHook(uc_engine* uc, uint32_t number, void* user_data)
20 | {
21 | uint64_t pc;
22 | uc_err err = uc_reg_read(uc, UC_ARM64_REG_PC, &pc);
23 |
24 | if (err != UC_ERR_OK)
25 | {
26 | // Don't handle this
27 | return;
28 | }
29 |
30 | SvcCall call_value;
31 | memset(&call_value, 0, sizeof(call_value));
32 |
33 | err = uc_mem_read(uc, pc - sizeof(SvcCall), &call_value, sizeof(call_value));
34 |
35 | if (err != UC_ERR_OK)
36 | {
37 | return;
38 | }
39 |
40 | // We are NOT handling a (valid) SVC interrupt
41 | if (number != 2 ||
42 | call_value.b1 != 1 ||
43 | call_value.b2 != 0 ||
44 | call_value.b3 != 0 ||
45 | call_value.b4 != 0 ||
46 | call_value.b5 != 212)
47 | {
48 | return;
49 | }
50 |
51 | const uint64_t syscallNumber = call_value.svcNumber;
52 |
53 | // Just grab a bunch of registers here so we don't have to make a bunch of calls
54 | // Being lazy =)
55 | uint64_t x0 = 0, x1 = 0, x2 = 0, x3 = 0, x4 = 0;
56 |
57 | err = uc_reg_read(uc, UC_ARM64_REG_X0, &x0); if (err != UC_ERR_OK) { return; }
58 | err = uc_reg_read(uc, UC_ARM64_REG_X1, &x1); if (err != UC_ERR_OK) { return; }
59 | err = uc_reg_read(uc, UC_ARM64_REG_X2, &x2); if (err != UC_ERR_OK) { return; }
60 | err = uc_reg_read(uc, UC_ARM64_REG_X3, &x3); if (err != UC_ERR_OK) { return; }
61 | err = uc_reg_read(uc, UC_ARM64_REG_X4, &x4); if (err != UC_ERR_OK) { return; }
62 |
63 | SyscallHandler(uc, user_data, syscallNumber, x0, x1, x2, x3, x4);
64 |
65 | err = uc_reg_write(uc, UC_ARM64_REG_X0, &x0); if (err != UC_ERR_OK) { return; }
66 | err = uc_reg_write(uc, UC_ARM64_REG_X1, &x1); if (err != UC_ERR_OK) { return; }
67 | err = uc_reg_write(uc, UC_ARM64_REG_X2, &x2); if (err != UC_ERR_OK) { return; }
68 | err = uc_reg_write(uc, UC_ARM64_REG_X3, &x3); if (err != UC_ERR_OK) { return; }
69 | err = uc_reg_write(uc, UC_ARM64_REG_X4, &x4); if (err != UC_ERR_OK) { return; }
70 | }
71 |
72 | bool ARM64Emulator::Initialize(void* buffer, size_t size)
73 | {
74 | uc_err err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &m_uc);
75 |
76 | if (err)
77 | {
78 | std::cerr << "[ERROR] Emulator uc_open failed with error [" << uc_strerror(err) << "]" << std::endl;
79 |
80 | return false;
81 | }
82 |
83 | m_alloc = new Allocator(m_uc, 4096U);
84 |
85 | if (!m_alloc->Map(buffer, size, nullptr))
86 | {
87 | std::cerr << "[ERROR] Allocator failed to map code." << std::endl;
88 |
89 | return false;
90 | }
91 |
92 | uint64_t stackAddress = 0;
93 | if (!m_alloc->Allocate(m_stackSize, &stackAddress))
94 | {
95 | std::cerr << "[ERROR] Allocator failed to allocate stack space." << std::endl;
96 |
97 | return false;
98 | }
99 |
100 | std::cout << ">>> Reserved " << std::hex << m_stackSize << std::dec << " bytes of stack space at address " << std::hex << stackAddress << std::dec << std::endl;
101 |
102 | // Often when functions are compiled with gcc, a real "function" will store x29 and x30 at sp-32
103 | // This will cause some serious issues if we don't give up some slack space
104 | uint64_t stackSlackSpaceAddress = stackAddress + 32;
105 |
106 | err = uc_reg_write(m_uc, UC_ARM64_REG_SP, &stackSlackSpaceAddress);
107 |
108 | if (err)
109 | {
110 | std::cerr << "[ERROR] Emulator uc_reg_write failed with error [" << uc_strerror(err) << "]" << std::endl;
111 |
112 | return false;
113 | }
114 |
115 | uc_hook trace;
116 | err = uc_hook_add(m_uc, &trace, UC_HOOK_INTR, ARM64_InterruptHook, this, 0, -1);
117 |
118 | if (err)
119 | {
120 | std::cerr << "[ERROR] Emulator uc_hook_add failed with error [" << uc_strerror(err) << "]" << std::endl;
121 |
122 | return false;
123 | }
124 |
125 | m_bufferSize = size;
126 |
127 | return true;
128 | }
129 |
130 | bool ARM64Emulator::Emulate()
131 | {
132 | uc_err err = uc_emu_start(m_uc, 0, m_bufferSize, 0, 0);
133 |
134 | if (err)
135 | {
136 | std::cerr << "[ERROR] Emulator uc_emu_start failed with error [" << uc_strerror(err) << "]" << std::endl;
137 | return false;
138 | }
139 |
140 | return true;
141 | }
142 |
143 | template
144 | uc_err ReadRegisterBatch(uc_engine* uc, const int (®isterIds)[N], uint64_t (&values)[N])
145 | {
146 | void* ptrs[N] = { nullptr };
147 |
148 | for (size_t i = 0; i < N; ++i)
149 | {
150 | ptrs[i] = &values[i];
151 | }
152 |
153 | return uc_reg_read_batch(uc, const_cast(registerIds), ptrs, N);
154 | }
155 |
156 | void ARM64Emulator::PrintContext(std::ostream& os)
157 | {
158 | const int regIds[] =
159 | {
160 | UC_ARM64_REG_X0,
161 | UC_ARM64_REG_X1,
162 | UC_ARM64_REG_X2,
163 | UC_ARM64_REG_X3,
164 | UC_ARM64_REG_X4,
165 | UC_ARM64_REG_X5,
166 | UC_ARM64_REG_PC,
167 | UC_ARM64_REG_FP,
168 | UC_ARM64_REG_LR
169 | };
170 |
171 | const char* regNames[] =
172 | {
173 | "X0",
174 | "X1",
175 | "X2",
176 | "X3",
177 | "X4",
178 | "X5",
179 | "PC",
180 | "FP",
181 | "LR"
182 | };
183 |
184 | os << "Context: {" << std::endl;
185 |
186 | constexpr size_t count = sizeof(regIds) / sizeof(int);
187 |
188 | uint64_t values[count] = { 0 };
189 |
190 | uc_err err = ReadRegisterBatch(m_uc, regIds, values);
191 | if (err)
192 | {
193 | os << "\t" << std::endl;
194 | }
195 | else
196 | {
197 | for (size_t i = 0; i < count; i++)
198 | {
199 | os << "\t" << regNames[i] << " = " << values[i] << std::endl;
200 | }
201 | }
202 |
203 | os << "}" << std::endl;
204 | }
205 |
206 | void ARM64Emulator::Close()
207 | {
208 | if (m_uc != nullptr)
209 | {
210 | uc_close(m_uc);
211 | }
212 |
213 | m_uc = nullptr;
214 | }
--------------------------------------------------------------------------------
/asm-trainer/aarch64emu.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class ARM64Emulator : public Emulator
4 | {
5 | public:
6 | ARM64Emulator(uint64_t stackSize) : Emulator(), m_bufferSize(0), m_stackSize(stackSize) {}
7 |
8 | bool Initialize(void* buffer, size_t size) override;
9 | bool Emulate() override;
10 | void PrintContext(std::ostream& os) override;
11 | void Close() override;
12 |
13 | private:
14 | uint64_t m_bufferSize;
15 | uint64_t m_stackSize;
16 | };
--------------------------------------------------------------------------------
/asm-trainer/allocator.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "unicorn/unicorn.h"
3 | #include "allocator.h"
4 |
5 | static uint64_t PageAlignUp(uint64_t pageSize, uint64_t address)
6 | {
7 | return (((address) + pageSize - 1) & -pageSize);
8 | }
9 |
10 | bool Allocator::Allocate(uint64_t size, uint64_t* address, uint32_t permissions)
11 | {
12 | size = PageAlignUp(m_pageSize, size);
13 |
14 | const uint64_t nearestAddress = FindNearestAvailableMemory(size);
15 |
16 | if (address)
17 | {
18 | *address = nearestAddress;
19 | }
20 |
21 | return Allocate(nearestAddress, size, permissions);
22 | }
23 |
24 | bool Allocator::Allocate(uint64_t address, uint64_t size, uint32_t permissions)
25 | {
26 | size = PageAlignUp(m_pageSize, size);
27 |
28 | if (IsMemoryRegionFree(address, size))
29 | {
30 | uc_err err = uc_mem_map(m_uc, address, size, permissions);
31 |
32 | if (err == UC_ERR_OK)
33 | {
34 | Mapping& map = m_mappings[address];
35 | map.address = address;
36 | map.size = size;
37 | map.permissions = permissions;
38 |
39 | return true;
40 | }
41 | }
42 |
43 | return false;
44 | }
45 |
46 | bool Allocator::Map(void* buffer, uint64_t size, uint64_t* address, uint32_t permissions)
47 | {
48 | size = PageAlignUp(m_pageSize, size);
49 |
50 | const uint64_t nearestAddress = FindNearestAvailableMemory(size);
51 |
52 | if (Map(buffer, nearestAddress, size, permissions))
53 | {
54 | if (address)
55 | {
56 | *address = nearestAddress;
57 | }
58 |
59 | return true;
60 | }
61 |
62 | return false;
63 | }
64 |
65 | bool Allocator::Map(void* buffer, uint64_t address, uint64_t size, uint32_t permissions)
66 | {
67 | size = PageAlignUp(m_pageSize, size);
68 |
69 | const uc_err err = uc_mem_map_ptr(m_uc, address, size, permissions, buffer);
70 |
71 | if (err == UC_ERR_OK)
72 | {
73 | Mapping& map = m_mappings[address];
74 | map.address = address;
75 | map.size = size;
76 | map.permissions = permissions;
77 |
78 | return true;
79 | }
80 |
81 | return false;
82 | }
83 |
84 | bool Allocator::Free(uint64_t address)
85 | {
86 | const auto entry = m_mappings.find(address);
87 | if (entry == m_mappings.end())
88 | {
89 | return false;
90 | }
91 |
92 | Mapping& mapping = (*entry).second;
93 |
94 | const uc_err err = uc_mem_unmap(m_uc, mapping.address, mapping.size);
95 |
96 | if (err == UC_ERR_OK)
97 | {
98 | m_mappings.erase(entry);
99 |
100 | return true;
101 | }
102 |
103 | return false;
104 | }
105 |
106 | bool Allocator::IsMemoryUnmapped(uint64_t address)
107 | {
108 | uint8_t i = 0;
109 | const uc_err err = uc_mem_read(m_uc, address, &i, sizeof(uint8_t));
110 | return (err == UC_ERR_READ_UNMAPPED);
111 | }
112 |
113 | bool Allocator::IsMemoryRegionFree(uint64_t address, uint64_t size)
114 | {
115 | const auto closeLow = m_mappings.lower_bound(address);
116 | if (closeLow == m_mappings.end())
117 | {
118 | // Nothing mapped yet
119 | return true;
120 | }
121 |
122 | Mapping& low_map = (*closeLow).second;
123 |
124 | // You only have to check the lower bound of the range in this instance
125 | if (low_map.IsWithinRange(address))
126 | {
127 | return false;
128 | }
129 |
130 | auto closeHigh = closeLow;
131 |
132 | // We need to check to see we don't bleed into the next entry
133 | if (++closeHigh != m_mappings.end())
134 | {
135 | Mapping& high_map = (*closeHigh).second;
136 |
137 |
138 | // You have to make sure address + size doesn't touch this either
139 | if (high_map.IsWithinRange(address) ||
140 | high_map.IsWithinRange(address + size))
141 | {
142 | return false;
143 | }
144 | }
145 |
146 | return true;
147 | }
148 |
149 | uint64_t Allocator::FindNearestAvailableMemory(uint64_t size)
150 | {
151 | if (m_mappings.empty())
152 | {
153 | return 0;
154 | }
155 |
156 | for (auto i = m_mappings.begin(); i != m_mappings.end(); ++i)
157 | {
158 | Mapping& current = (*i).second;
159 |
160 | auto next = i;
161 |
162 | // We can check if there's space in between entries suitable for us
163 | if (++next != m_mappings.end())
164 | {
165 | Mapping& next_entry = (*next).second;
166 |
167 | uint64_t slack = next_entry.address - (current.address + current.size);
168 |
169 | if (slack >= size)
170 | {
171 | return (current.address + current.size);
172 | }
173 | }
174 | else
175 | {
176 | // Just give them the next available space
177 | return (current.address + current.size);
178 | }
179 | }
180 |
181 | __assume(false);
182 | }
183 |
--------------------------------------------------------------------------------
/asm-trainer/allocator.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class Allocator
4 | {
5 | struct Mapping
6 | {
7 | uint64_t address;
8 | uint64_t size;
9 | uint32_t permissions;
10 |
11 | bool IsWithinRange(uint64_t addr)
12 | {
13 | return (addr >= address && addr < (address + size));
14 | }
15 | };
16 |
17 | public:
18 | Allocator() = delete;
19 | Allocator(uc_engine* uc, uint64_t pageSize) : m_uc(uc), m_pageSize(pageSize) {}
20 |
21 | bool Allocate(uint64_t size, uint64_t* address, uint32_t permissions = UC_PROT_ALL);
22 | bool Allocate(uint64_t address, uint64_t size, uint32_t permissions = UC_PROT_ALL);
23 |
24 | bool Map(void* buffer, uint64_t size, uint64_t* address, uint32_t permissions = UC_PROT_ALL);
25 | bool Map(void* buffer, uint64_t address, uint64_t size, uint32_t permissions = UC_PROT_ALL);
26 |
27 | bool Free(uint64_t address);
28 |
29 | bool IsMemoryUnmapped(uint64_t address);
30 | bool IsMemoryRegionFree(uint64_t address, uint64_t size);
31 |
32 | std::map& GetMappings() { return m_mappings; }
33 |
34 | private:
35 | uint64_t FindNearestAvailableMemory(uint64_t size);
36 |
37 | uc_engine* m_uc;
38 | uint64_t m_pageSize;
39 | std::map m_mappings;
40 | };
--------------------------------------------------------------------------------
/asm-trainer/asm-trainer.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "cxxopts.hpp"
4 | #include "unicorn/unicorn.h"
5 | #include "keystone/keystone.h"
6 |
7 | #include "allocator.h"
8 |
9 | #include "emu.h"
10 | #include "aarch64emu.h"
11 | #include "aarch32emu.h"
12 | #include "x64emu.h"
13 | #include "x86emu.h"
14 |
15 | #include "assembler.h"
16 | #include "aarch64asm.h"
17 | #include "aarch32asm.h"
18 | #include "x64asm.h"
19 | #include "x86asm.h"
20 |
21 | #include "exercise.h"
22 | #include "math_exercises.h"
23 |
24 | cxxopts::Options options("asm-trainer", "Assembly Trainer");
25 |
26 | bool parse_options(int& argc, char**& argv, std::string& engine, std::string& filename, std::string& output_filename, int& stack_size)
27 | {
28 | try
29 | {
30 | options.add_options()
31 | ("e,engine", "Assembly engine to use (aarch32, aarch64)", cxxopts::value())
32 | ("f,file", "File to assemble and run the emulator against", cxxopts::value())
33 | ("o,output", "Optional parameter to output assembled bytes into a file", cxxopts::value())
34 | ("s,stack-size", "Optional parameter to specify the amount of bytes in stack space you require", cxxopts::value());
35 |
36 | auto result = options.parse(argc, argv);
37 |
38 | if (result.count("e") == 0 ||
39 | result.count("f") == 0)
40 | {
41 | return false;
42 | }
43 |
44 | engine = result["e"].as();
45 | filename = result["f"].as();
46 |
47 | if (result.count("o"))
48 | {
49 | output_filename = result["o"].as();
50 | }
51 |
52 | if (result.count("s"))
53 | {
54 | stack_size = result["s"].as();
55 | }
56 | else
57 | {
58 | stack_size = 4096;
59 | }
60 |
61 | return true;
62 | }
63 | catch (std::exception& e)
64 | {
65 | std::cout << "EXCEPTION [" << e.what() << "]" << std::endl;
66 |
67 | return false;
68 | }
69 | }
70 |
71 | bool read_file(std::string& filename, std::string& file_content)
72 | {
73 | std::ifstream file(filename);
74 |
75 | if (!file.good())
76 | {
77 | return false;
78 | }
79 |
80 | file_content = std::string((std::istreambuf_iterator(file)), std::istreambuf_iterator());
81 |
82 | return true;
83 | }
84 |
85 | bool write_binary_file(std::string& filename, std::vector& binary_content)
86 | {
87 | std::ofstream file(filename, std::ios::out | std::ios::binary);
88 |
89 | if (!file.good())
90 | {
91 | return false;
92 | }
93 |
94 | file.write(reinterpret_cast(binary_content.data()), binary_content.size());
95 | file.close();
96 |
97 | return true;
98 | }
99 |
100 | int main(int argc, char** argv, char** envp)
101 | {
102 | int stackSize = 0;
103 | std::string engine, filename, output_filename;
104 | if (!parse_options(argc, argv, engine, filename, output_filename, stackSize))
105 | {
106 | std::cout << "Failed to parse program options." << std::endl << std::endl;
107 | std::cout << options.help();
108 | return -1;
109 | }
110 |
111 | std::string file_content;
112 | if (!read_file(filename, file_content))
113 | {
114 | std::cout << "The file provided [" << filename << "] could not be read." << std::endl;
115 | return -1;
116 | }
117 |
118 | // Need to assemble the file
119 |
120 | // Need to emulate the result
121 | int status = -1;
122 |
123 | std::vector assembled_code;
124 |
125 | Emulator* emu = nullptr;
126 | Assembler* assembler = nullptr;
127 |
128 | if (engine == "aarch64")
129 | {
130 | emu = new ARM64Emulator(stackSize);
131 | assembler = new ARM64Assembler;
132 |
133 | std::cout << ">>> Using aarch64 emulator and assembler engines." << std::endl;
134 | }
135 | else if (engine == "aarch32")
136 | {
137 | emu = new ARM32Emulator(stackSize);
138 | assembler = new ARM32Assembler;
139 |
140 | std::cout << ">>> Using aarch32 emulator and assembler engines." << std::endl;
141 | }
142 | else if (engine == "x64")
143 | {
144 | emu = new X64Emulator(stackSize);
145 | assembler = new X64Assembler;
146 | }
147 | else if (engine == "x86")
148 | {
149 | emu = new X86Emulator(stackSize);
150 | assembler = new X86Assembler;
151 | }
152 | else
153 | {
154 | std::cerr << ">>> Engine \"" << engine << "\" is not supported." << std::endl;
155 | goto end;
156 | }
157 |
158 | if (!assembler->Initialize())
159 | {
160 | std::cout << ">>> Failed to initialize the assembler engine." << std::endl;
161 | goto end;
162 | }
163 |
164 | if (!assembler->Assemble(file_content, assembled_code))
165 | {
166 | std::cout << ">>> Failed to assemble provided file." << std::endl;
167 | goto end;
168 | }
169 |
170 | std::cout << ">>> Assembled code is " << assembled_code.size() << " bytes." << std::endl;
171 |
172 | if (!output_filename.empty())
173 | {
174 | std::cout << ">>> Writing assembled output to " << output_filename << std::endl;
175 |
176 | if (!write_binary_file(output_filename, assembled_code))
177 | {
178 | std::cerr << ">>> Unable to write output file " << output_filename << std::endl;
179 | goto end;
180 | }
181 | }
182 |
183 | if (!emu->Initialize((void *) assembled_code.data(), assembled_code.size()))
184 | {
185 | std::cout << "Failed to initialize emulation engine." << std::endl;
186 | goto end;
187 | }
188 |
189 | std::cout << ">>> Entering emulation state" << std::endl << std::endl;
190 | // std::cout << "============================" << std::endl;
191 |
192 | if (!emu->Emulate())
193 | {
194 | std::cout << ">>> Failed to emulate code." << std::endl;
195 | goto end;
196 | }
197 |
198 | // std::cout << "============================" << std::endl;
199 |
200 | std::cout << std::endl;
201 |
202 | emu->PrintContext(std::cout);
203 |
204 | status = 0;
205 |
206 | end:
207 | if (emu != nullptr)
208 | {
209 | emu->Close();
210 | }
211 |
212 | delete emu;
213 | delete assembler;
214 |
215 | return status;
216 | }
--------------------------------------------------------------------------------
/asm-trainer/asm-trainer.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | 15.0
23 | {1A4BF274-4B5F-44DC-A36D-2DEBFEE48529}
24 | Win32Proj
25 | asmtrainer
26 | 10.0.17763.0
27 |
28 |
29 |
30 | Application
31 | true
32 | v141
33 | Unicode
34 |
35 |
36 | Application
37 | false
38 | v141
39 | true
40 | Unicode
41 |
42 |
43 | Application
44 | true
45 | v141
46 | Unicode
47 |
48 |
49 | Application
50 | false
51 | v141
52 | true
53 | Unicode
54 | false
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | true
76 |
77 |
78 | true
79 |
80 |
81 | false
82 |
83 |
84 | false
85 |
86 |
87 |
88 | Use
89 | Level3
90 | Disabled
91 | true
92 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
93 | true
94 | pch.h
95 |
96 |
97 | Console
98 | true
99 |
100 |
101 |
102 |
103 | Use
104 | Level3
105 | Disabled
106 | true
107 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
108 | true
109 | pch.h
110 |
111 |
112 | Console
113 | true
114 |
115 |
116 |
117 |
118 | Use
119 | Level3
120 | MaxSpeed
121 | true
122 | true
123 | true
124 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
125 | true
126 | pch.h
127 |
128 |
129 | Console
130 | true
131 | true
132 | true
133 |
134 |
135 |
136 |
137 | Use
138 | Level3
139 | MaxSpeed
140 | true
141 | true
142 |
143 |
144 | NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
145 | true
146 | pch.h
147 | $(SolutionDir)ext/unicorn/include;$(SolutionDir)ext/cxxopts/include;$(SolutionDir)ext/keystone/include;%(AdditionalIncludeDirectories)
148 | false
149 | MultiThreaded
150 |
151 |
152 | Console
153 | true
154 | true
155 | true
156 | aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;x86_64-softmmu.lib;unicorn_lib.lib;$(SolutionDir)ext/keystone/build/llvm/lib/keystone.lib;%(AdditionalDependencies)
157 | $(SolutionDir)$(Platform)\$(Configuration)\
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 | Create
188 | Create
189 | Create
190 | Create
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
--------------------------------------------------------------------------------
/asm-trainer/asm-trainer.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {59f35728-86ea-4b9b-9576-e2292b84e8c9}
14 |
15 |
16 | {7eb81ea1-7a16-49fc-9b5f-d3c771a8b0df}
17 |
18 |
19 | {063235a0-8a05-45a3-8ff0-87cc2c4717c0}
20 |
21 |
22 | {6ac6ccaf-935a-4da3-a3f8-a443dd89f703}
23 |
24 |
25 | {f4da41d0-3f2e-422b-96b0-15bb9139724e}
26 |
27 |
28 | {f14485b5-2f9a-4170-bb6c-57c97c85f02a}
29 |
30 |
31 |
32 |
33 | Header Files
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files\emu
43 |
44 |
45 | Header Files\emu
46 |
47 |
48 | Header Files\assembler
49 |
50 |
51 | Header Files\assembler
52 |
53 |
54 | Header Files\assembler
55 |
56 |
57 | Header Files\assembler
58 |
59 |
60 | Header Files\emu
61 |
62 |
63 | Header Files\emu
64 |
65 |
66 | Header Files\emu
67 |
68 |
69 | Header Files\emu
70 |
71 |
72 | Header Files\emu
73 |
74 |
75 | Header Files\exercises
76 |
77 |
78 | Header Files\exercises
79 |
80 |
81 |
82 |
83 | Source Files
84 |
85 |
86 | Source Files
87 |
88 |
89 | Source Files\emu
90 |
91 |
92 | Source Files\emu
93 |
94 |
95 | Source Files\assembler
96 |
97 |
98 | Source Files\assembler
99 |
100 |
101 | Source Files\assembler
102 |
103 |
104 | Source Files\assembler
105 |
106 |
107 | Source Files\emu
108 |
109 |
110 | Source Files\emu
111 |
112 |
113 | Source Files\emu
114 |
115 |
116 | Source Files\emu
117 |
118 |
119 | Source Files\exercises
120 |
121 |
122 |
--------------------------------------------------------------------------------
/asm-trainer/asm-trainer.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/asm-trainer/assembler.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class Assembler
4 | {
5 | public:
6 | virtual bool Initialize() = 0;
7 | virtual bool Assemble(std::string& assembly, std::vector& encoded) = 0;
8 |
9 | protected:
10 | ks_engine* m_ks;
11 | };
--------------------------------------------------------------------------------
/asm-trainer/emu.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct uc_struct;
4 | typedef struct uc_struct uc_engine;
5 |
6 | class Emulator
7 | {
8 | public:
9 | Emulator() : m_uc(nullptr)
10 | {
11 | }
12 |
13 | virtual bool Initialize(void* buffer, size_t size) = 0;
14 | virtual bool Emulate() = 0;
15 | virtual void PrintContext(std::ostream& os) = 0;
16 | virtual void Close() = 0;
17 |
18 | uc_engine* GetEngine() const { return m_uc; }
19 | Allocator* GetAllocator() const { return m_alloc; }
20 |
21 | template
22 | bool is()
23 | {
24 | return (dynamic_cast(this) != nullptr);
25 | }
26 |
27 | protected:
28 | Allocator* m_alloc;
29 | uc_engine* m_uc;
30 | };
--------------------------------------------------------------------------------
/asm-trainer/exercise.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class Emulator;
4 |
5 | class Exercise
6 | {
7 | public:
8 | Exercise() = delete;
9 | Exercise(Emulator* emu) : m_emu(emu) {}
10 |
11 | virtual bool InitializeEngineState() = 0;
12 | virtual bool Evaluate() = 0;
13 |
14 | protected:
15 | Emulator* m_emu;
16 | };
--------------------------------------------------------------------------------
/asm-trainer/math_exercises.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "unicorn/unicorn.h"
3 | #include "allocator.h"
4 | #include "emu.h"
5 | #include "aarch32emu.h"
6 | #include "aarch64emu.h"
7 | #include "x64emu.h"
8 | #include "x86emu.h"
9 | #include "exercise.h"
10 | #include "math_exercises.h"
11 |
12 | // Simple test, take parameters passed to your function and
13 | // 0x12 ^ 0x75 == 0x67
14 |
15 | bool SimpleXorExercise::InitializeEngineState()
16 | {
17 | uint64_t arg1 = 0x12;
18 | uint64_t arg2 = 0x75;
19 |
20 | if (ARM64Emulator* aarch64 = dynamic_cast(m_emu))
21 | {
22 | if (uc_reg_write(m_emu->GetEngine(), UC_ARM64_REG_X0, &arg1) != UC_ERR_OK ||
23 | uc_reg_write(m_emu->GetEngine(), UC_ARM64_REG_X1, &arg2) != UC_ERR_OK)
24 | {
25 | return false;
26 | }
27 | }
28 | else if (ARM32Emulator* aarch32 = dynamic_cast(m_emu))
29 | {
30 | if (uc_reg_write(m_emu->GetEngine(), UC_ARM_REG_R0, &arg1) != UC_ERR_OK ||
31 | uc_reg_write(m_emu->GetEngine(), UC_ARM_REG_R1, &arg2) != UC_ERR_OK)
32 | {
33 | return false;
34 | }
35 | }
36 | else if (X64Emulator* x64 = dynamic_cast(m_emu))
37 | {
38 | if (uc_reg_write(m_emu->GetEngine(), UC_X86_REG_RCX, &arg1) != UC_ERR_OK ||
39 | uc_reg_write(m_emu->GetEngine(), UC_X86_REG_RDX, &arg2) != UC_ERR_OK)
40 | {
41 | return false;
42 | }
43 | }
44 | else if (X86Emulator* x86 = dynamic_cast(m_emu))
45 | {
46 | uint64_t esp = 0;
47 |
48 | if (uc_reg_read(m_emu->GetEngine(), UC_X86_REG_ESP, &esp) != UC_ERR_OK)
49 | {
50 | return false;
51 | }
52 |
53 | if (uc_mem_write(m_emu->GetEngine(), esp + 4, &arg1, sizeof(uint32_t)) != UC_ERR_OK ||
54 | uc_mem_write(m_emu->GetEngine(), esp + 8, &arg2, sizeof(uint32_t)) != UC_ERR_OK)
55 | {
56 | return false;
57 | }
58 |
59 | }
60 |
61 | return true;
62 | }
63 |
64 | bool SimpleXorExercise::Evaluate()
65 | {
66 | uint64_t result = 0;
67 |
68 | uc_err err = UC_ERR_OK;
69 |
70 | if (ARM64Emulator* aarch64 = dynamic_cast(m_emu))
71 | {
72 | err = uc_reg_read(m_emu->GetEngine(), UC_ARM64_REG_X0, &result);
73 | }
74 | else if (ARM32Emulator* aarch32 = dynamic_cast(m_emu))
75 | {
76 | err = uc_reg_read(m_emu->GetEngine(), UC_ARM_REG_R0, &result);
77 | }
78 | else if (X64Emulator* x64 = dynamic_cast(m_emu))
79 | {
80 | err = uc_reg_read(m_emu->GetEngine(), UC_X86_REG_RAX, &result);
81 | }
82 | else if (X86Emulator* x86 = dynamic_cast(m_emu))
83 | {
84 | err = uc_reg_read(m_emu->GetEngine(), UC_X86_REG_EAX, &result);
85 | }
86 |
87 | if (err != UC_ERR_OK)
88 | {
89 | return false;
90 | }
91 |
92 | if (result != 0x67)
93 | {
94 | return false;
95 | }
96 |
97 | return true;
98 | }
--------------------------------------------------------------------------------
/asm-trainer/math_exercises.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | class SimpleXorExercise : public Exercise
4 | {
5 | public:
6 | SimpleXorExercise(Emulator* emu) : Exercise(emu) {}
7 |
8 | bool InitializeEngineState() override;
9 | bool Evaluate() override;
10 | };
--------------------------------------------------------------------------------
/asm-trainer/pch.cpp:
--------------------------------------------------------------------------------
1 | // pch.cpp: source file corresponding to pre-compiled header; necessary for compilation to succeed
2 |
3 | #include "pch.h"
4 |
5 | // In general, ignore this file, but keep it around if you are using pre-compiled headers.
6 |
--------------------------------------------------------------------------------
/asm-trainer/pch.h:
--------------------------------------------------------------------------------
1 | #ifndef PCH_H
2 | #define PCH_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include