├── .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 8 | #include 9 | #include 10 | 11 | #endif //PCH_H 12 | -------------------------------------------------------------------------------- /asm-trainer/syscall.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "unicorn/unicorn.h" 3 | #include "syscall.h" 4 | #include "util.h" 5 | #include "allocator.h" 6 | #include "emu.h" 7 | #include "aarch32emu.h" 8 | #include "aarch64emu.h" 9 | #include "x86emu.h" 10 | #include "x64emu.h" 11 | 12 | typedef void(*SyscallHandler_t)(uc_engine* uc, void* userdata, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4); 13 | 14 | struct RegisteredSyscall 15 | { 16 | uint64_t syscallIndex; 17 | SyscallHandler_t handler; 18 | }; 19 | 20 | void exit(uc_engine* uc, void* userdata, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4) 21 | { 22 | uc_emu_stop(uc); 23 | } 24 | 25 | void print(uc_engine* uc, void* userdata, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4) 26 | { 27 | ret = 0; 28 | 29 | std::string str; 30 | if (emuutil::ReadStringFromMemory(uc, arg1, str)) 31 | { 32 | puts(str.c_str()); 33 | 34 | ret = 1; 35 | } 36 | } 37 | 38 | void map_memory(uc_engine* uc, void* userdata, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4) 39 | { 40 | const uc_err err = uc_mem_map(uc, arg1, arg2, UC_PROT_ALL); 41 | 42 | ret = (err == UC_ERR_OK) ? 1 : 0; 43 | } 44 | 45 | void unmap_memory(uc_engine* uc, void* userdata, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4) 46 | { 47 | const uc_err err = uc_mem_unmap(uc, arg1, arg2); 48 | 49 | ret = (err == UC_ERR_OK) ? 1 : 0; 50 | } 51 | 52 | void is_mem_mapped(uc_engine* uc, void* userdata, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4) 53 | { 54 | uint8_t i = 0; 55 | const uc_err err = uc_mem_read(uc, arg1, &i, sizeof(uint8_t)); 56 | ret = (err == UC_ERR_READ_UNMAPPED) ? 0 : 1; 57 | } 58 | 59 | void print_char(uc_engine* uc, void* userdata, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4) 60 | { 61 | putc(static_cast(arg1), stdout); 62 | 63 | ret = 1; 64 | } 65 | 66 | RegisteredSyscall registered_handlers[] = 67 | { 68 | { SYSCALL_EXIT, exit }, 69 | { SYSCALL_PRINT, print }, 70 | { SYSCALL_MAP, map_memory }, 71 | { SYSCALL_UNMAP, unmap_memory }, 72 | { SYSCALL_MEM_MAPPED, is_mem_mapped }, 73 | { SYSCALL_PRINT_CHAR, print_char }, 74 | }; 75 | 76 | void SyscallHandler(uc_engine* uc, void* userdata, uint32_t syscall, uint32_t& ret, uint32_t& arg1, uint32_t& arg2, uint32_t& arg3, uint32_t& arg4) 77 | { 78 | const uint64_t syscallExt = syscall; 79 | 80 | uint64_t retExt = ret; 81 | uint64_t arg1Ext = arg1; 82 | uint64_t arg2Ext = arg2; 83 | uint64_t arg3Ext = arg3; 84 | uint64_t arg4Ext = arg4; 85 | 86 | SyscallHandler(uc, userdata, syscallExt, retExt, arg1Ext, arg2Ext, arg3Ext, arg4Ext); 87 | 88 | ret = static_cast(retExt); 89 | arg1 = static_cast(arg1Ext); 90 | arg2 = static_cast(arg2Ext); 91 | arg3 = static_cast(arg3Ext); 92 | arg4 = static_cast(arg4Ext); 93 | } 94 | 95 | void SyscallHandler(uc_engine* uc, void* userdata, uint64_t syscall, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4) 96 | { 97 | if (syscall < _countof(registered_handlers)) 98 | { 99 | registered_handlers[syscall].handler(uc, userdata, ret, arg1, arg2, arg3, arg4); 100 | } 101 | } -------------------------------------------------------------------------------- /asm-trainer/syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | enum SyscallIndices 4 | { 5 | SYSCALL_EXIT, // Stop emulation 6 | SYSCALL_PRINT, // Print string 7 | SYSCALL_MAP, // Map memory to address 8 | SYSCALL_UNMAP, // Unmap memory 9 | SYSCALL_MEM_MAPPED, // Check if memory is mapped in 10 | SYSCALL_PRINT_CHAR, // This makes things a little easier by printing a single char 11 | 12 | ////////////////////////////////////////////////////////////////////////// 13 | 14 | SYSCALL_EX_ADD_4 = 1000, // Add 5 parameters fed into this function using standard argument format 15 | }; 16 | 17 | extern void SyscallHandler(uc_engine* uc, void* userdata, uint32_t syscall, uint32_t& ret, uint32_t& arg1, uint32_t& arg2, uint32_t& arg3, uint32_t& arg4); 18 | extern void SyscallHandler(uc_engine* uc, void* userdata, uint64_t syscall, uint64_t& ret, uint64_t& arg1, uint64_t& arg2, uint64_t& arg3, uint64_t& arg4); -------------------------------------------------------------------------------- /asm-trainer/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace emuutil 4 | { 5 | static bool ReadStringFromMemory(uc_engine* uc, uint64_t addr, std::string& output) 6 | { 7 | while (true) 8 | { 9 | char c = 0; 10 | const uc_err err = uc_mem_read(uc, addr, &c, sizeof(char)); 11 | 12 | if (err != UC_ERR_OK) 13 | { 14 | return false; 15 | } 16 | 17 | output.push_back(c); 18 | 19 | if (c == 0) 20 | { 21 | break; 22 | } 23 | 24 | ++addr; 25 | } 26 | 27 | return true; 28 | } 29 | } -------------------------------------------------------------------------------- /asm-trainer/x64asm.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "keystone/keystone.h" 3 | #include "assembler.h" 4 | #include "x64asm.h" 5 | 6 | bool X64Assembler::Initialize() 7 | { 8 | ks_err err = ks_open(KS_ARCH_X86, KS_MODE_64, &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 | err = ks_option(m_ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_INTEL); 17 | 18 | if (err != KS_ERR_OK) 19 | { 20 | std::cerr << "[ERROR] ks_option failed [" << ks_strerror(err) << "]" << std::endl; 21 | return false; 22 | } 23 | 24 | return true; 25 | } 26 | 27 | bool X64Assembler::Assemble(std::string& assembly, std::vector& encoded) 28 | { 29 | size_t size = 0, count = 0; 30 | 31 | unsigned char* enc = nullptr; 32 | 33 | const int result = ks_asm(m_ks, assembly.c_str(), 0, &enc, &size, &count); 34 | 35 | if (result != 0) 36 | { 37 | const char* errorDescription = ks_strerror(ks_errno(m_ks)); 38 | 39 | std::cerr << "[ERROR] Assembly engine ks_asm returned error after executing " << count << " statements (" << errorDescription << ")" << std::endl; 40 | return false; 41 | } 42 | 43 | if (size == 0) 44 | { 45 | std::cerr << "[ERROR] Generated assembly from ks_asm is 0 bytes." << std::endl; 46 | return false; 47 | } 48 | 49 | encoded.resize(size); 50 | 51 | memcpy(encoded.data(), enc, size); 52 | 53 | ks_free(enc); 54 | ks_close(m_ks); 55 | 56 | m_ks = nullptr; 57 | 58 | return true; 59 | } -------------------------------------------------------------------------------- /asm-trainer/x64asm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class X64Assembler : public Assembler 4 | { 5 | public: 6 | virtual bool Initialize() override; 7 | virtual bool Assemble(std::string& assembly, std::vector& encoded) override; 8 | }; -------------------------------------------------------------------------------- /asm-trainer/x64emu.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "unicorn/unicorn.h" 3 | #include "allocator.h" 4 | #include "emu.h" 5 | #include "x64emu.h" 6 | #include "syscall.h" 7 | 8 | static void X64_SyscallHook(uc_engine* uc, void* user_data) 9 | { 10 | uint64_t syscallIndex = 0; 11 | 12 | uc_err err = uc_reg_read(uc, UC_X86_REG_RAX, &syscallIndex); 13 | 14 | // Just grab a bunch of registers here so we don't have to make a bunch of calls 15 | // Being lazy =) 16 | uint64_t rax = 0, rbx = 0, rcx = 0, rdx = 0, r8 = 0, r9 = 0; 17 | 18 | uc_reg_read(uc, UC_X86_REG_RAX, &rax); 19 | uc_reg_read(uc, UC_X86_REG_RCX, &rcx); 20 | uc_reg_read(uc, UC_X86_REG_RDX, &rdx); 21 | uc_reg_read(uc, UC_X86_REG_R8, &r8); 22 | uc_reg_read(uc, UC_X86_REG_R9, &r9); 23 | 24 | SyscallHandler(uc, user_data, syscallIndex, rax, rcx, rdx, r8, r9); 25 | 26 | uc_reg_write(uc, UC_X86_REG_RAX, &rax); 27 | uc_reg_write(uc, UC_X86_REG_RCX, &rcx); 28 | uc_reg_write(uc, UC_X86_REG_RDX, &rdx); 29 | uc_reg_write(uc, UC_X86_REG_R8, &r8); 30 | uc_reg_write(uc, UC_X86_REG_R9, &r9); 31 | } 32 | 33 | bool X64Emulator::Initialize(void* buffer, size_t size) 34 | { 35 | uc_err err = uc_open(UC_ARCH_X86, UC_MODE_64, &m_uc); 36 | 37 | if (err) 38 | { 39 | std::cerr << "[ERROR] Emulator uc_open failed with error [" << uc_strerror(err) << "]" << std::endl; 40 | 41 | return false; 42 | } 43 | 44 | m_alloc = new Allocator(m_uc, 4096U); 45 | 46 | if (!m_alloc->Map(buffer, size, nullptr)) 47 | { 48 | std::cerr << "[ERROR] Allocator failed to map code." << std::endl; 49 | 50 | return false; 51 | } 52 | 53 | uint64_t stackAddress = 0; 54 | if (!m_alloc->Allocate(m_stackSize, &stackAddress)) 55 | { 56 | std::cerr << "[ERROR] Allocator failed to allocate stack space." << std::endl; 57 | 58 | return false; 59 | } 60 | 61 | std::cout << ">>> Reserved " << std::hex << m_stackSize << std::dec << " bytes of stack space at address " << std::hex << stackAddress << std::dec << std::endl; 62 | 63 | err = uc_reg_write(m_uc, UC_X86_REG_RSP, &stackAddress); 64 | 65 | if (err) 66 | { 67 | std::cerr << "[ERROR] Emulator uc_reg_write failed with error [" << uc_strerror(err) << "]" << std::endl; 68 | 69 | return false; 70 | } 71 | 72 | uc_hook syscall; 73 | err = uc_hook_add(m_uc, &syscall, UC_HOOK_INSN, X64_SyscallHook, this, 1, 0, UC_X86_INS_SYSCALL); 74 | 75 | if (err) 76 | { 77 | std::cerr << "[ERROR] Emulator uc_hook_add failed with error [" << uc_strerror(err) << "]" << std::endl; 78 | 79 | return false; 80 | } 81 | 82 | m_bufferSize = size; 83 | 84 | return true; 85 | } 86 | 87 | bool X64Emulator::Emulate() 88 | { 89 | uc_err err = uc_emu_start(m_uc, 0, m_bufferSize, 0, 0); 90 | 91 | if (err) 92 | { 93 | std::cerr << "[ERROR] Emulator uc_emu_start failed with error [" << uc_strerror(err) << "]" << std::endl; 94 | 95 | PrintContext(std::cerr); 96 | 97 | return false; 98 | } 99 | 100 | return true; 101 | } 102 | 103 | template 104 | uc_err ReadRegisterBatch(uc_engine* uc, const int(®isterIds)[N], uint64_t(&values)[N]) 105 | { 106 | void* ptrs[N] = { nullptr }; 107 | 108 | for (size_t i = 0; i < N; ++i) 109 | { 110 | ptrs[i] = &values[i]; 111 | } 112 | 113 | return uc_reg_read_batch(uc, const_cast(registerIds), ptrs, N); 114 | } 115 | 116 | void X64Emulator::PrintContext(std::ostream& os) 117 | { 118 | const int regIds[] = 119 | { 120 | UC_X86_REG_RAX, 121 | UC_X86_REG_RBX, 122 | UC_X86_REG_RCX, 123 | UC_X86_REG_RDX, 124 | UC_X86_REG_R8, 125 | UC_X86_REG_R9, 126 | UC_X86_REG_RIP, 127 | UC_X86_REG_RSP 128 | }; 129 | 130 | const char* regNames[] = 131 | { 132 | "RAX", 133 | "RBX", 134 | "RCX", 135 | "RDX", 136 | "R8", 137 | "R9", 138 | "RIP", 139 | "RSP" 140 | }; 141 | 142 | os << "Context: {" << std::endl; 143 | 144 | constexpr size_t count = sizeof(regIds) / sizeof(int); 145 | 146 | uint64_t values[count] = { 0 }; 147 | 148 | uc_err err = ReadRegisterBatch(m_uc, regIds, values); 149 | if (err) 150 | { 151 | os << "\t" << std::endl; 152 | } 153 | else 154 | { 155 | for (size_t i = 0; i < count; i++) 156 | { 157 | os << "\t" << regNames[i] << " = " << values[i] << std::endl; 158 | } 159 | } 160 | 161 | os << "}" << std::endl; 162 | } 163 | 164 | void X64Emulator::Close() 165 | { 166 | if (m_uc != nullptr) 167 | uc_close(m_uc); 168 | 169 | m_uc = nullptr; 170 | } -------------------------------------------------------------------------------- /asm-trainer/x64emu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class X64Emulator : public Emulator 4 | { 5 | public: 6 | X64Emulator(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/x86asm.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "keystone/keystone.h" 3 | #include "assembler.h" 4 | #include "x86asm.h" 5 | 6 | bool X86Assembler::Initialize() 7 | { 8 | ks_err err = ks_open(KS_ARCH_X86, KS_MODE_32, &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 X86Assembler::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/x86asm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class X86Assembler : public Assembler 4 | { 5 | public: 6 | virtual bool Initialize() override; 7 | virtual bool Assemble(std::string& assembly, std::vector& encoded) override; 8 | }; -------------------------------------------------------------------------------- /asm-trainer/x86emu.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "unicorn/unicorn.h" 3 | #include "allocator.h" 4 | #include "emu.h" 5 | #include "x86emu.h" 6 | #include "syscall.h" 7 | 8 | static void X86_SyscallHook(uc_engine* uc, void* user_data) 9 | { 10 | uc_err err = UC_ERR_OK; 11 | 12 | uint32_t syscallIndex = 0, stackPointer = 0; 13 | 14 | err = uc_reg_read(uc, UC_X86_REG_EAX, &syscallIndex); 15 | err = uc_reg_read(uc, UC_X86_REG_ESP, &stackPointer); 16 | 17 | // In x86 we have to read stack variables instead of registers. 18 | // I'd really _like_ to use registers because it's easier, but we're trying to teach people stuff here =) 19 | 20 | uint32_t eax = 0; 21 | uint32_t arg1 = 0, arg2 = 0, arg3 = 0, arg4 = 0; 22 | 23 | uc_reg_read(uc, UC_X86_REG_EAX, &eax); 24 | 25 | uc_mem_read(uc, stackPointer + 0x04, &arg1, sizeof(uint32_t)); 26 | uc_mem_read(uc, stackPointer + 0x08, &arg2, sizeof(uint32_t)); 27 | uc_mem_read(uc, stackPointer + 0x0C, &arg3, sizeof(uint32_t)); 28 | uc_mem_read(uc, stackPointer + 0x10, &arg4, sizeof(uint32_t)); 29 | 30 | SyscallHandler(uc, user_data, syscallIndex, eax, arg1, arg2, arg3, arg4); 31 | 32 | uc_reg_write(uc, UC_X86_REG_EAX, &eax); 33 | 34 | uc_mem_write(uc, stackPointer + 0x04, &arg1, sizeof(uint32_t)); 35 | uc_mem_write(uc, stackPointer + 0x08, &arg2, sizeof(uint32_t)); 36 | uc_mem_write(uc, stackPointer + 0x0C, &arg3, sizeof(uint32_t)); 37 | uc_mem_write(uc, stackPointer + 0x10, &arg4, sizeof(uint32_t)); 38 | } 39 | 40 | bool X86Emulator::Initialize(void* buffer, size_t size) 41 | { 42 | uc_err err = uc_open(UC_ARCH_X86, UC_MODE_32, &m_uc); 43 | 44 | if (err) 45 | { 46 | std::cerr << "[ERROR] Emulator uc_open failed with error [" << uc_strerror(err) << "]" << std::endl; 47 | 48 | return false; 49 | } 50 | 51 | m_alloc = new Allocator(m_uc, 4096U); 52 | 53 | if (!m_alloc->Map(buffer, size, nullptr)) 54 | { 55 | std::cerr << "[ERROR] Allocator failed to map code." << std::endl; 56 | 57 | return false; 58 | } 59 | 60 | uint64_t stackAddress = 0; 61 | if (!m_alloc->Allocate(m_stackSize, &stackAddress)) 62 | { 63 | std::cerr << "[ERROR] Allocator failed to allocate stack space." << std::endl; 64 | 65 | return false; 66 | } 67 | 68 | std::cout << ">>> Reserved " << std::hex << m_stackSize << std::dec << " bytes of stack space at address " << std::hex << stackAddress << std::dec << std::endl; 69 | 70 | err = uc_reg_write(m_uc, UC_X86_REG_ESP, &stackAddress); 71 | 72 | if (err) 73 | { 74 | std::cerr << "[ERROR] Emulator uc_reg_write failed with error [" << uc_strerror(err) << "]" << std::endl; 75 | 76 | return false; 77 | } 78 | 79 | uc_hook syscall; 80 | err = uc_hook_add(m_uc, &syscall, UC_HOOK_INSN, X86_SyscallHook, (void *)(int)UC_X86_INS_SYSCALL, 1, 0, UC_X86_INS_SYSCALL); 81 | 82 | if (err) 83 | { 84 | std::cerr << "[ERROR] Emulator uc_hook_add failed with error [" << uc_strerror(err) << "]" << std::endl; 85 | 86 | return false; 87 | } 88 | 89 | m_bufferSize = size; 90 | 91 | return true; 92 | } 93 | 94 | bool X86Emulator::Emulate() 95 | { 96 | uc_err err = uc_emu_start(m_uc, 0, m_bufferSize, 0, 0); 97 | 98 | if (err) 99 | { 100 | std::cerr << "[ERROR] Emulator uc_emu_start failed with error [" << uc_strerror(err) << "]" << std::endl; 101 | return false; 102 | } 103 | 104 | return true; 105 | } 106 | 107 | template 108 | uc_err ReadRegisterBatch(uc_engine* uc, const int(®isterIds)[N], uint64_t(&values)[N]) 109 | { 110 | void* ptrs[N] = { nullptr }; 111 | 112 | for (size_t i = 0; i < N; ++i) 113 | { 114 | ptrs[i] = &values[i]; 115 | } 116 | 117 | return uc_reg_read_batch(uc, const_cast(registerIds), ptrs, N); 118 | } 119 | 120 | void X86Emulator::PrintContext(std::ostream& os) 121 | { 122 | const int regIds[] = 123 | { 124 | UC_X86_REG_EAX, 125 | UC_X86_REG_EBX, 126 | UC_X86_REG_ECX, 127 | UC_X86_REG_EDX, 128 | UC_X86_REG_EIP, 129 | UC_X86_REG_ESP 130 | }; 131 | 132 | const char* regNames[] = 133 | { 134 | "EAX", 135 | "EBX", 136 | "ECX", 137 | "EDX", 138 | "EIP", 139 | "ESP" 140 | }; 141 | 142 | os << "Context: {" << std::endl; 143 | 144 | constexpr size_t count = sizeof(regIds) / sizeof(int); 145 | 146 | uint64_t values[count] = { 0 }; 147 | 148 | uc_err err = ReadRegisterBatch(m_uc, regIds, values); 149 | if (err) 150 | { 151 | os << "\t" << std::endl; 152 | } 153 | else 154 | { 155 | for (size_t i = 0; i < count; i++) 156 | { 157 | os << "\t" << regNames[i] << " = " << values[i] << std::endl; 158 | } 159 | } 160 | 161 | os << "}" << std::endl; 162 | } 163 | 164 | void X86Emulator::Close() 165 | { 166 | if (m_uc != nullptr) 167 | uc_close(m_uc); 168 | 169 | m_uc = nullptr; 170 | } -------------------------------------------------------------------------------- /asm-trainer/x86emu.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class X86Emulator : public Emulator 4 | { 5 | public: 6 | X86Emulator(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 | }; -------------------------------------------------------------------------------- /examples/aarch32.s: -------------------------------------------------------------------------------- 1 | main: 2 | ldr r0, .L2 3 | bl print 4 | b exit 5 | 6 | exit: 7 | svc #0 /* calls uc_emu_stop to cease emulation, that's why we won't return */ 8 | 9 | print: 10 | mov r1, r0 /* r1 is the first argument for our syscall functions, r0 will store the result */ 11 | svc #1 /* print to console */ 12 | mov pc, lr /* simulated ret */ 13 | 14 | .LC0: 15 | .ascii "Hello, World!\000" 16 | 17 | .L2: 18 | .word .LC0 -------------------------------------------------------------------------------- /examples/aarch64.s: -------------------------------------------------------------------------------- 1 | main: 2 | adrp x1, .LC0 3 | add x1, x1, #:lo12:.LC0 4 | bl print 5 | b exit 6 | 7 | exit: 8 | svc #0 9 | 10 | print: 11 | svc #1 12 | ret 13 | 14 | .LC0: 15 | .string "I did it!" -------------------------------------------------------------------------------- /examples/simplexor-aarch32.s: -------------------------------------------------------------------------------- 1 | simplexor_exercise: 2 | EOR r0, r1 -------------------------------------------------------------------------------- /examples/simplexor-aarch64.s: -------------------------------------------------------------------------------- 1 | simplexor_exercise: 2 | EOR x0, x0, x1 -------------------------------------------------------------------------------- /examples/simplexor-x64.s: -------------------------------------------------------------------------------- 1 | simplexor_exercise: 2 | xor rcx, rdx 3 | mov rax, rcx -------------------------------------------------------------------------------- /examples/simplexor-x86.s: -------------------------------------------------------------------------------- 1 | simplexor_exercise: 2 | mov ebx, [esp+4] 3 | mov ecx, [esp+8] 4 | xor ebx, ecx 5 | mov eax, ebx -------------------------------------------------------------------------------- /examples/x64-mem-mapped.s: -------------------------------------------------------------------------------- 1 | main: 2 | call test_mapped 3 | call map_memory 4 | call test_mapped 5 | call try_set_mem 6 | call exit 7 | 8 | try_set_mem: 9 | mov rax, qword ptr [mem_address] 10 | mov qword ptr [rax], 4 11 | cmp qword ptr [rax], 4 12 | jz mem_ok 13 | mov rcx, write_memory_test_failed 14 | call print 15 | jmp end_of_try_set_mem 16 | mem_ok: 17 | mov rcx, write_memory_test_ok 18 | call print 19 | end_of_try_set_mem: 20 | ret 21 | 22 | test_mapped: 23 | mov rcx, [mem_address] 24 | call is_mem_mapped 25 | cmp rax, 0 26 | jz main_not_mapped 27 | mov rcx, mem_mapped 28 | call print 29 | jmp end_of_test_mapped 30 | main_not_mapped: 31 | mov rcx, mem_not_mapped 32 | call print 33 | end_of_test_mapped: 34 | ret 35 | 36 | map_memory: 37 | mov rcx, attempting_map 38 | call print 39 | mov rax, 2 40 | mov rcx, [mem_address] 41 | mov rdx, 0x1000 42 | syscall 43 | ret 44 | 45 | is_mem_mapped: 46 | mov rax, 4 47 | syscall 48 | ret 49 | 50 | exit: 51 | mov rax, 0 52 | syscall 53 | 54 | print: 55 | mov rax, 1 56 | syscall 57 | ret 58 | 59 | mem_address: 60 | .quad 0x4000 61 | mem_not_mapped: 62 | .string "The memory at 0x4000 is not mapped" 63 | mem_mapped: 64 | .string "The memory at 0x4000 is mapped" 65 | attempting_map: 66 | .string "Attempting to map memory at 0x4000" 67 | write_memory_test_failed: 68 | .string "Attempted to write value to 0x4000 and failed." 69 | write_memory_test_ok: 70 | .string "Wrote a value to 0x4000 successfully!" -------------------------------------------------------------------------------- /examples/x64.s: -------------------------------------------------------------------------------- 1 | main: 2 | mov rcx, HelloWorld 3 | call print 4 | call exit 5 | 6 | exit: 7 | mov rax, 0 8 | syscall 9 | 10 | print: 11 | mov rax, 1 12 | syscall 13 | ret 14 | 15 | HelloWorld: 16 | .string "Hello, World!" -------------------------------------------------------------------------------- /examples/x86.s: -------------------------------------------------------------------------------- 1 | main: 2 | push HelloWorld 3 | call print 4 | add esp, 4 5 | call exit 6 | 7 | exit: 8 | mov eax, 0 9 | syscall 10 | 11 | print: 12 | mov eax, 1 13 | syscall /* syscall takes esp+4 as the first argument, but the push already shifted the stack before this call, so we don't have to access it */ 14 | ret 15 | 16 | HelloWorld: 17 | .string "Hello, World!" -------------------------------------------------------------------------------- /unicorn_lib/unicorn_lib.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 | 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 | 15.0 174 | {0A4AB8B4-712D-4867-8DA4-B12DE2B9B40B} 175 | Win32Proj 176 | unicornlib 177 | 10.0.17763.0 178 | 179 | 180 | 181 | StaticLibrary 182 | true 183 | v141 184 | Unicode 185 | 186 | 187 | StaticLibrary 188 | false 189 | v141 190 | true 191 | Unicode 192 | 193 | 194 | StaticLibrary 195 | true 196 | v141 197 | Unicode 198 | 199 | 200 | StaticLibrary 201 | false 202 | v141 203 | false 204 | Unicode 205 | false 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | false 227 | 228 | 229 | true 230 | 231 | 232 | true 233 | 234 | 235 | false 236 | 237 | 238 | 239 | NotUsing 240 | Level3 241 | MaxSpeed 242 | true 243 | true 244 | 245 | 246 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;__x86_64__;UNICORN_HAS_ARM64;UNICORN_HAS_ARM;UNICORN_HAS_X86;WIN32_LEAN_AND_MEAN 247 | false 248 | $(SolutionDir)ext/unicorn/include;$(SolutionDir)ext/unicorn/qemu;$(SolutionDir)ext/unicorn/qemu/include;$(SolutionDir)ext/unicorn/qemu/tcg;$(SolutionDir)ext/unicorn/msvc/unicorn;%(AdditionalIncludeDirectories) 249 | ProgramDatabase 250 | false 251 | false 252 | MultiThreaded 253 | 254 | 255 | Windows 256 | true 257 | true 258 | true 259 | 260 | 261 | aarch64-softmmu.lib;aarch64eb-softmmu.lib;arm-softmmu.lib;armeb-softmmu.lib;x86_64-softmmu.lib 262 | 263 | 264 | $(SolutionDir)$(Platform)\$(Configuration)\ 265 | 266 | 267 | 268 | 269 | 270 | false 271 | 272 | 273 | 274 | 275 | Use 276 | Level3 277 | Disabled 278 | true 279 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 280 | true 281 | 282 | 283 | Windows 284 | true 285 | 286 | 287 | 288 | 289 | Use 290 | Level3 291 | Disabled 292 | true 293 | _DEBUG;_LIB;%(PreprocessorDefinitions) 294 | true 295 | 296 | 297 | Windows 298 | true 299 | 300 | 301 | 302 | 303 | Use 304 | Level3 305 | MaxSpeed 306 | true 307 | true 308 | true 309 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 310 | true 311 | 312 | 313 | Windows 314 | true 315 | true 316 | true 317 | 318 | 319 | 320 | 321 | 322 | -------------------------------------------------------------------------------- /unicorn_lib/unicorn_lib.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {9b422248-1cc1-4e5b-ac8b-4b9ed1c39d42} 6 | 7 | 8 | {edab7e43-7a8b-49cc-8295-a89e574b2971} 9 | 10 | 11 | {6fa7fb3a-61d0-460c-9350-d2c561671a27} 12 | 13 | 14 | {5a8cb3f2-1c19-4cdf-8df7-9ede0bc1ff5f} 15 | 16 | 17 | {66f00452-c906-4a8e-abae-aba4deb45d0a} 18 | 19 | 20 | {18ad5d1f-3d26-43b8-be7c-4974d4b01b26} 21 | 22 | 23 | {8259ffde-0a7d-4fa4-8d93-368d0f4080f9} 24 | 25 | 26 | {8521fd47-b966-4a14-88d0-349b7885c19f} 27 | 28 | 29 | {fcb37279-47b5-4d82-ab67-966e0db8581a} 30 | 31 | 32 | {b1408822-11bf-4d0b-8294-f6a13311073a} 33 | 34 | 35 | {8159ee32-ecfc-4273-9290-257ef27f9fff} 36 | 37 | 38 | {ae32919a-6113-48e9-b5ee-22ffaa1da0cc} 39 | 40 | 41 | {3fc1d5bd-8106-4280-813f-4796a6cad8ec} 42 | 43 | 44 | {57aa820a-22f4-409c-8830-c67836ad7c46} 45 | 46 | 47 | {b79d73e4-1234-4db8-aac4-0bcd20e748a4} 48 | 49 | 50 | {6ff88e63-592c-4eec-8db4-c201ccdc0723} 51 | 52 | 53 | {73812677-340d-420c-adef-9d466fd0090a} 54 | 55 | 56 | {ddf0ecd2-db9f-4f05-bc00-11536af51597} 57 | 58 | 59 | {b55aea93-18f6-478a-bb71-71042fb05a5a} 60 | 61 | 62 | {5e95b133-2058-4d28-a32d-15ffacebb043} 63 | 64 | 65 | {9be10d1e-29fa-4a91-9ac8-add09bdf951b} 66 | 67 | 68 | {ca04efd3-eeb0-47e2-a9d8-df11847faea8} 69 | 70 | 71 | {4b1e45da-a59c-4742-9cbf-65fdbfd712d5} 72 | 73 | 74 | 75 | 76 | priv 77 | 78 | 79 | qemu 80 | 81 | 82 | qemu 83 | 84 | 85 | qemu 86 | 87 | 88 | qemu 89 | 90 | 91 | qemu 92 | 93 | 94 | qemu 95 | 96 | 97 | qemu 98 | 99 | 100 | qemu 101 | 102 | 103 | qemu\util 104 | 105 | 106 | qemu\util 107 | 108 | 109 | qemu\util 110 | 111 | 112 | qemu\util 113 | 114 | 115 | qemu\util 116 | 117 | 118 | qemu\util 119 | 120 | 121 | qemu\util 122 | 123 | 124 | qemu\util 125 | 126 | 127 | qemu\util 128 | 129 | 130 | qemu\util 131 | 132 | 133 | qemu\util 134 | 135 | 136 | qemu\util 137 | 138 | 139 | qemu\util 140 | 141 | 142 | qemu\hw\core 143 | 144 | 145 | qemu\hw\core 146 | 147 | 148 | qemu\qapi 149 | 150 | 151 | qemu\qapi 152 | 153 | 154 | qemu\qapi 155 | 156 | 157 | qemu\qapi 158 | 159 | 160 | qemu\qapi 161 | 162 | 163 | qemu\qobject 164 | 165 | 166 | qemu\qobject 167 | 168 | 169 | qemu\qobject 170 | 171 | 172 | qemu\qobject 173 | 174 | 175 | qemu\qobject 176 | 177 | 178 | qemu\qobject 179 | 180 | 181 | qemu\qobject 182 | 183 | 184 | qemu\qom 185 | 186 | 187 | qemu\qom 188 | 189 | 190 | qemu\qom 191 | 192 | 193 | qemu\qom 194 | 195 | 196 | 197 | 198 | 199 | priv 200 | 201 | 202 | priv 203 | 204 | 205 | priv 206 | 207 | 208 | qemu 209 | 210 | 211 | qemu 212 | 213 | 214 | qemu 215 | 216 | 217 | qemu 218 | 219 | 220 | qemu\include 221 | 222 | 223 | qemu\include 224 | 225 | 226 | qemu\include 227 | 228 | 229 | qemu\include 230 | 231 | 232 | qemu\include\exec 233 | 234 | 235 | qemu\include\exec 236 | 237 | 238 | qemu\include\exec 239 | 240 | 241 | qemu\include\exec 242 | 243 | 244 | qemu\include\exec 245 | 246 | 247 | qemu\include\exec 248 | 249 | 250 | qemu\include\exec 251 | 252 | 253 | qemu\include\exec 254 | 255 | 256 | qemu\include\exec 257 | 258 | 259 | qemu\include\exec 260 | 261 | 262 | qemu\include\exec 263 | 264 | 265 | qemu\include\exec 266 | 267 | 268 | qemu\include\exec 269 | 270 | 271 | qemu\include\exec 272 | 273 | 274 | qemu\include\exec 275 | 276 | 277 | qemu\include\exec 278 | 279 | 280 | qemu\include\exec 281 | 282 | 283 | qemu\include\exec 284 | 285 | 286 | qemu\include\exec 287 | 288 | 289 | qemu\include\exec 290 | 291 | 292 | qemu\include\exec 293 | 294 | 295 | qemu\include\fpu 296 | 297 | 298 | qemu\include\hw 299 | 300 | 301 | qemu\include\hw 302 | 303 | 304 | qemu\include\hw 305 | 306 | 307 | qemu\include\hw 308 | 309 | 310 | qemu\include\hw 311 | 312 | 313 | qemu\include\hw\arm 314 | 315 | 316 | qemu\include\hw\cpu 317 | 318 | 319 | qemu\include\hw\i386 320 | 321 | 322 | qemu\include\hw\i386 323 | 324 | 325 | qemu\include\hw\i386 326 | 327 | 328 | qemu\include\hw\m68k 329 | 330 | 331 | qemu\include\hw\m68k 332 | 333 | 334 | qemu\include\hw\mips 335 | 336 | 337 | qemu\include\hw\mips 338 | 339 | 340 | qemu\include\hw\mips 341 | 342 | 343 | qemu\include\hw\sparc 344 | 345 | 346 | qemu\include\hw\sparc 347 | 348 | 349 | qemu\include\hw\sparc 350 | 351 | 352 | qemu\include\hw\sparc 353 | 354 | 355 | qemu\include\qapi 356 | 357 | 358 | qemu\include\qapi 359 | 360 | 361 | qemu\include\qapi 362 | 363 | 364 | qemu\include\qapi 365 | 366 | 367 | qemu\include\qapi 368 | 369 | 370 | qemu\include\qapi 371 | 372 | 373 | qemu\include\qapi 374 | 375 | 376 | qemu\include\qapi 377 | 378 | 379 | qemu\include\qapi\qmp 380 | 381 | 382 | qemu\include\qapi\qmp 383 | 384 | 385 | qemu\include\qapi\qmp 386 | 387 | 388 | qemu\include\qapi\qmp 389 | 390 | 391 | qemu\include\qapi\qmp 392 | 393 | 394 | qemu\include\qapi\qmp 395 | 396 | 397 | qemu\include\qapi\qmp 398 | 399 | 400 | qemu\include\qapi\qmp 401 | 402 | 403 | qemu\include\qapi\qmp 404 | 405 | 406 | qemu\include\qapi\qmp 407 | 408 | 409 | qemu\include\qemu 410 | 411 | 412 | qemu\include\qemu 413 | 414 | 415 | qemu\include\qemu 416 | 417 | 418 | qemu\include\qemu 419 | 420 | 421 | qemu\include\qemu 422 | 423 | 424 | qemu\include\qemu 425 | 426 | 427 | qemu\include\qemu 428 | 429 | 430 | qemu\include\qemu 431 | 432 | 433 | qemu\include\qemu 434 | 435 | 436 | qemu\include\qemu 437 | 438 | 439 | qemu\include\qemu 440 | 441 | 442 | qemu\include\qemu 443 | 444 | 445 | qemu\include\qemu 446 | 447 | 448 | qemu\include\qemu 449 | 450 | 451 | qemu\include\qemu 452 | 453 | 454 | qemu\include\qemu 455 | 456 | 457 | qemu\include\qemu 458 | 459 | 460 | qemu\include\qemu 461 | 462 | 463 | qemu\include\qemu 464 | 465 | 466 | qemu\include\qemu 467 | 468 | 469 | qemu\include\qom 470 | 471 | 472 | qemu\include\qom 473 | 474 | 475 | qemu\include\qom 476 | 477 | 478 | qemu\include\sysemu 479 | 480 | 481 | qemu\include\sysemu 482 | 483 | 484 | qemu\include\sysemu 485 | 486 | 487 | qemu\include\sysemu 488 | 489 | 490 | qemu\include\sysemu 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | -------------------------------------------------------------------------------- /unicorn_lib/unicorn_lib.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /x86_64-softmmu/x86_64-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 | 46 | 47 | 48 | 49 | true 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 | 15.0 81 | {8C3AD934-3C92-4CEC-B06C-68697E9FD558} 82 | Win32Proj 83 | x8664softmmu 84 | 10.0.17763.0 85 | 86 | 87 | 88 | StaticLibrary 89 | true 90 | v141 91 | Unicode 92 | 93 | 94 | StaticLibrary 95 | false 96 | v141 97 | true 98 | Unicode 99 | 100 | 101 | StaticLibrary 102 | true 103 | v141 104 | Unicode 105 | 106 | 107 | StaticLibrary 108 | false 109 | v141 110 | false 111 | MultiByte 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | false 133 | 134 | 135 | true 136 | 137 | 138 | true 139 | 140 | 141 | false 142 | 143 | 144 | 145 | 146 | 147 | Level3 148 | Disabled 149 | true 150 | false 151 | 152 | 153 | WIN32;NDEBUG;_LIB;__x86_64__;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;inline=__inline;__func__=__FUNCTION__;NEED_CPU_H;WIN32_LEAN_AND_MEAN 154 | false 155 | $(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-i386;$(SolutionDir)ext/unicorn/msvc/unicorn;$(SolutionDir)ext/unicorn/msvc/unicorn/x86_64-softmmu;%(AdditionalIncludeDirectories) 156 | None 157 | false 158 | false 159 | MultiThreaded 160 | x86_64.h 161 | false 162 | 163 | 164 | Windows 165 | true 166 | true 167 | true 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | Use 176 | Level3 177 | Disabled 178 | true 179 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 180 | true 181 | 182 | 183 | Windows 184 | true 185 | 186 | 187 | 188 | 189 | Use 190 | Level3 191 | Disabled 192 | true 193 | _DEBUG;_LIB;%(PreprocessorDefinitions) 194 | true 195 | 196 | 197 | Windows 198 | true 199 | 200 | 201 | 202 | 203 | Use 204 | Level3 205 | MaxSpeed 206 | true 207 | true 208 | true 209 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 210 | true 211 | 212 | 213 | Windows 214 | true 215 | true 216 | true 217 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /x86_64-softmmu/x86_64-softmmu.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {df87866c-9f1a-48b6-99ef-8c98447f64ec} 6 | 7 | 8 | {388b4375-16d3-48e1-9e0f-538ff8d0d107} 9 | 10 | 11 | {faa69310-1c51-4a38-8014-e99df9dcf5ed} 12 | 13 | 14 | {b29fe974-14fe-4d95-8d9e-7d32f081674f} 15 | 16 | 17 | {b98c98f2-946a-4f28-8e5d-f41d3135cd7b} 18 | 19 | 20 | {ec600655-416d-40a3-9fed-8f4b1fb88ffe} 21 | 22 | 23 | {89271c9c-521d-428b-bb5f-903a8b53a543} 24 | 25 | 26 | 27 | 28 | fpu 29 | 30 | 31 | hw\i386 32 | 33 | 34 | hw\i386 35 | 36 | 37 | hw\intc 38 | 39 | 40 | hw\intc 41 | 42 | 43 | target-i386 44 | 45 | 46 | target-i386 47 | 48 | 49 | target-i386 50 | 51 | 52 | target-i386 53 | 54 | 55 | target-i386 56 | 57 | 58 | target-i386 59 | 60 | 61 | target-i386 62 | 63 | 64 | target-i386 65 | 66 | 67 | target-i386 68 | 69 | 70 | target-i386 71 | 72 | 73 | target-i386 74 | 75 | 76 | target-i386 77 | 78 | 79 | target-i386 80 | 81 | 82 | target-i386 83 | 84 | 85 | tcg\i386 86 | 87 | 88 | tcg 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | tcg 100 | 101 | 102 | 103 | 104 | fpu 105 | 106 | 107 | fpu 108 | 109 | 110 | target-i386 111 | 112 | 113 | target-i386 114 | 115 | 116 | target-i386 117 | 118 | 119 | target-i386 120 | 121 | 122 | target-i386 123 | 124 | 125 | target-i386 126 | 127 | 128 | target-i386 129 | 130 | 131 | target-i386 132 | 133 | 134 | target-i386 135 | 136 | 137 | target-i386 138 | 139 | 140 | tcg\i386 141 | 142 | 143 | tcg 144 | 145 | 146 | tcg 147 | 148 | 149 | tcg 150 | 151 | 152 | tcg 153 | 154 | 155 | tcg 156 | 157 | 158 | tcg 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /x86_64-softmmu/x86_64-softmmu.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------