У рамках сустрэчы 0x0A DC7831
У артыкуле мы прывядзем апісанне запуску прашыўкі прылады ў эмулятары, прадэманструем узаемадзеянне з адладчыкам і выканаем невялікі дынамічны аналіз прашыўкі.
перадгісторыя
У long time in galaxy far far away
Пару гадоў таму ў нашай лабараторыі ўзнікла неабходнасць даследаваць прашыўку прылады. Прашыўка была сціснутая, распакоўвалася bootloader'ам. Рабіў ён гэта вельмі затлумленым спосабам, некалькі разоў перакладаючы дадзеныя ў памяці. Ды і сама прашыўка потым актыўна ўзаемадзейнічала з перыферыяй. І ўсё гэта на ядры MIPS.
Наяўныя эмулятары па аб'ектыўных чынніках нас не задаволілі, а жадалася ўсёткі запусціць код. Тады вырашылі зрабіць свой эмулятар, які зробіць мінімум і дазволіць распакаваць асноўную прашыўку. Паспрабавалі - атрымалася. Падумалі, а што калі дадаць перыферыю, каб яшчэ і асноўную прашыўку выконваць. Было не вельмі балюча - і таксама атрымалася. Зноў падумалі і вырашылі рабіць паўнавартасны эмулятар.
У выніку атрымаўся эмулятар вылічальных сістэм
Чаму Kopycat?
Мае месца гульня слоў.
- copycat (англ., наз. [ˈkɒpɪkæt]) — пераймальнік, імітатар
- котка (англ., наз. [ˈkæt]) — котка, кот — любімая жывёла аднаго са стваральнікаў праекта
- Літара "K" - ад мовы праграмавання Kotlin
Kopycat
Пры стварэнні эмулятара ставіліся зусім вызначаныя мэты:
- магчымасць дастаткова хутка стварыць новую перыферыю, модуль, працэсарнае ядро;
- магчымасць сабраць віртуальную прыладу з розных модуляў;
- магчымасць загрузіць у памяць віртуальнай прылады любыя двайковыя дадзеныя (прашыўку);
- магчымасць працы са снапшотамі (здымкі стану сістэмы);
- магчымасць узаемадзеяння з эмулятарам праз убудаваны адладчык;
- прыемны сучасную мову для распрацоўкі.
У выніку, для рэалізацыі быў абраны Kotlin, шынная архітэктура (гэта калі модулі звязваюцца паміж сабой праз віртуальныя шыны дадзеных), JSON – у якасці фармату апісання прылады, і GDB RSP – у якасці пратакола ўзаемадзеяння з адладчыкам.
Распрацоўка ідзе на працягу крыху больш за два гады і актыўна працягваецца. За гэты час былі рэалізаваны працэсарныя ядры MIPS, x86, V850ES, ARM, PowerPC.
Праект расце, і прыйшоў час прадставіць яго шырокай грамадскасці. Падрабязнае апісанне праекта зробім пазней, а зараз засяродзімся на выкарыстанні Kopycat.
Для самых нецярплівых - прома-версію эмулятара можна спампаваць па
Насарог у эмулятары
Нагадаем, раней для канферэнцыі SMARTRHINO-2018 была створана тэставая прылада «Насарог» для навучання навыкам рэверс-інжынірынгу. Працэс статычнага аналізу прашыўкі быў апісаны ў
Цяпер жа паспрабуем дадаць "дынамікі" і запусцім прашыўку ў эмулятары.
Нам спатрэбяцца:
1) Java 1.8
2) Python і модуль
Для Windows:
1)
2)
Для Linux:
1) socat
У якасці GDB-кліента можна выкарыстоўваць Eclipse, IDA Pro ці radare2.
Як гэта працуе?
Для таго, каб выконваць прашыўку ў эмулятары, неабходна "сабраць" віртуальную прыладу, якое ўяўляе сабой аналаг рэальнай прылады.
Рэальную прыладу («насарог») можна паказаць на структурнай схеме:
Эмулятар мае модульную структуру і канчатковая віртуальная прылада можна апісаць у JSON-файле.
JSON на 105 радкоў
{
"top": true,
// Plugin name should be the same as file name (or full path from library start)
"plugin": "rhino",
// Directory where plugin places
"library": "user",
// Plugin parameters (constructor parameters if jar-plugin version)
"params": [
{ "name": "tty_dbg", "type": "String"},
{ "name": "tty_bt", "type": "String"},
{ "name": "firmware", "type": "String", "default": "NUL"}
],
// Plugin outer ports
"ports": [ ],
// Plugin internal buses
"buses": [
{ "name": "mem", "size": "BUS30" },
{ "name": "nand", "size": "4" },
{ "name": "gpio", "size": "BUS32" }
],
// Plugin internal components
"modules": [
{
"name": "u1_stm32",
"plugin": "STM32F042",
"library": "mcu",
"params": {
"firmware:String": "params.firmware"
}
},
{
"name": "usart_debug",
"plugin": "UartSerialTerminal",
"library": "terminals",
"params": {
"tty": "params.tty_dbg"
}
},
{
"name": "term_bt",
"plugin": "UartSerialTerminal",
"library": "terminals",
"params": {
"tty": "params.tty_bt"
}
},
{
"name": "bluetooth",
"plugin": "BT",
"library": "mcu"
},
{ "name": "led_0", "plugin": "LED", "library": "mcu" },
{ "name": "led_1", "plugin": "LED", "library": "mcu" },
{ "name": "led_2", "plugin": "LED", "library": "mcu" },
{ "name": "led_3", "plugin": "LED", "library": "mcu" },
{ "name": "led_4", "plugin": "LED", "library": "mcu" },
{ "name": "led_5", "plugin": "LED", "library": "mcu" },
{ "name": "led_6", "plugin": "LED", "library": "mcu" },
{ "name": "led_7", "plugin": "LED", "library": "mcu" },
{ "name": "led_8", "plugin": "LED", "library": "mcu" },
{ "name": "led_9", "plugin": "LED", "library": "mcu" },
{ "name": "led_10", "plugin": "LED", "library": "mcu" },
{ "name": "led_11", "plugin": "LED", "library": "mcu" },
{ "name": "led_12", "plugin": "LED", "library": "mcu" },
{ "name": "led_13", "plugin": "LED", "library": "mcu" },
{ "name": "led_14", "plugin": "LED", "library": "mcu" },
{ "name": "led_15", "plugin": "LED", "library": "mcu" }
],
// Plugin connection between components
"connections": [
[ "u1_stm32.ports.usart1_m", "usart_debug.ports.term_s"],
[ "u1_stm32.ports.usart1_s", "usart_debug.ports.term_m"],
[ "u1_stm32.ports.usart2_m", "bluetooth.ports.usart_m"],
[ "u1_stm32.ports.usart2_s", "bluetooth.ports.usart_s"],
[ "bluetooth.ports.bt_s", "term_bt.ports.term_m"],
[ "bluetooth.ports.bt_m", "term_bt.ports.term_s"],
[ "led_0.ports.pin", "u1_stm32.buses.pin_output_a", "0x00"],
[ "led_1.ports.pin", "u1_stm32.buses.pin_output_a", "0x01"],
[ "led_2.ports.pin", "u1_stm32.buses.pin_output_a", "0x02"],
[ "led_3.ports.pin", "u1_stm32.buses.pin_output_a", "0x03"],
[ "led_4.ports.pin", "u1_stm32.buses.pin_output_a", "0x04"],
[ "led_5.ports.pin", "u1_stm32.buses.pin_output_a", "0x05"],
[ "led_6.ports.pin", "u1_stm32.buses.pin_output_a", "0x06"],
[ "led_7.ports.pin", "u1_stm32.buses.pin_output_a", "0x07"],
[ "led_8.ports.pin", "u1_stm32.buses.pin_output_a", "0x08"],
[ "led_9.ports.pin", "u1_stm32.buses.pin_output_a", "0x09"],
[ "led_10.ports.pin", "u1_stm32.buses.pin_output_a", "0x0A"],
[ "led_11.ports.pin", "u1_stm32.buses.pin_output_a", "0x0B"],
[ "led_12.ports.pin", "u1_stm32.buses.pin_output_a", "0x0C"],
[ "led_13.ports.pin", "u1_stm32.buses.pin_output_a", "0x0D"],
[ "led_14.ports.pin", "u1_stm32.buses.pin_output_a", "0x0E"],
[ "led_15.ports.pin", "u1_stm32.buses.pin_output_a", "0x0F"]
]
}
Звярніце ўвагу на параметр прашыўкі у раздзеле ПАРАМЕТРЫ - гэта імя файла, які можна загружаць у віртуальную прыладу ў якасці прашыўкі.
Віртуальная прылада і яго ўзаемадзеянне з асноўнай аперацыйнай сістэмай можна прадставіць вось такой схемай:
Бягучы тэставы асобнік эмулятара мае на ўвазе ўзаемадзеянне з COM-партамі асноўнай АС (адладкавы UART і UART для Bluetooth-модуля). Гэта могуць быць рэальныя парты, да якіх падлучаныя прылады ці ж віртуальныя COM-парты (для гэтага як раз патрэбен com0com / socat).
Для ўзаемадзеяння з эмулятарам звонку на дадзены момант існуе два асноўных спосабу:
- пратакол GDB RSP (адпаведна, якія падтрымліваюць гэты пратакол, прылады - Eclipse / IDA / radare2);
- унутраны камандны радок эмулятара (Argparse або Python).
Віртуальныя COM-парты
Для таго каб узаемадзейнічаць з UART-ом віртуальнай прылады на лакальнай машыне праз тэрмінал, неабходна стварыць пару злучаных віртуальных COM-партоў. У нашым выпадку адзін порт задзейнічае эмулятар, а другі - праграма-тэрмінал (PuTTY або screen):
Выкарыстанне com0com
Віртуальныя COM-парты наладжваюцца setup-утылітай з камплекта com0com (кансольная версія — C:Program Files (x86)com0comsetupс.exe, або GUI-версія - C:Program Files (x86)com0comsetupg.exe):
Варта ўсталяваць галачкі enable buffer overrun для ўсіх створаных віртуальных партоў, інакш эмулятар будзе чакаць водгуку ад COM-порта.
Выкарыстанне socat
На UNIX-сістэмах віртуальныя COM-парты аўтаматычна ствараюцца эмулятарам пры дапамозе ўтыліты socat, для гэтага досыць пры запуску эмулятара ў імі порта паказаць прэфікс. socat:
.
Унутраны інтэрфейс каманднага радка (Argparse ці Python)
Паколькі Kopycat уяўляе сабой кансольнае прыкладанне, для ўзаемадзеяння са сваімі аб'ектамі і зменнымі эмулятар падае два варыянту інтэрфейсу каманднага радка: Argparse і Python.
Argparse – гэта CLI, убудаваны ў Kopycat, ён даступны заўсёды і ўсім.
Альтэрнатыўны CLI – інтэрпрэтатар Python. Для яго выкарыстання неабходна ўсталяваць Python-модуль Jep і наладзіць эмулятар для працы з Python (будзе выкарыстоўвацца інтэрпрэтатар Python, усталяваны ў асноўнай сістэме карыстальніка).
Ўстаноўка Python-модуля Jep
Пад Linux Jep можа быць усталяваны праз pip:
pip install jep
Для ўсталёўкі Jep пад Windows неабходна папярэдне ўсталяваць Windows SDK і якая адпавядае Microsoft Visual Studio. Мы крыху спрасцілі вам задачу і зрабілі
pip install jep-3.8.2-cp27-cp27m-win_amd64.whl
Для праверкі ўсталёўкі Jep, неабходна выканаць у камандным радку:
python -c "import jep"
У адказ павінна быць атрымана паведамленне:
ImportError: Jep is not supported in standalone Python, it must be embedded in Java.
У камандным файле эмулятара для вашай сістэмы (kopycat.bat - для Windows, kopycat - для Linux) да спісу параметраў DEFAULT_JVM_OPTS
дадайце дадатковы параметр Djava.library.path
- ён павінен утрымоўваць шлях да ўсталяванага модуля Jep.
У выніку для Windows павінен атрымацца радок наступнага выгляду:
set DEFAULT_JVM_OPTS="-XX:MaxMetaspaceSize=256m" "-XX:+UseParallelGC" "-XX:SurvivorRatio=6" "-XX:-UseGCOverheadLimit" "-Djava.library.path=C:/Python27/Lib/site-packages/jep"
Запуск Kopycat
Эмулятар уяўляе сабой кансольнае JVM-дадатак. Запуск ажыццяўляецца праз сцэнар каманднага радка аперацыйнай сістэмы (sh/cmd).
Каманда для запуску пад Windows:
binkopycat -g 23946 -n rhino -l user -y library -p firmware=firmwarerhino_pass.bin,tty_dbg=COM26,tty_bt=COM28
Каманда для запуску пад Linux з выкарыстаннем утыліты socat:
./bin/kopycat -g 23946 -n rhino -l user -y library -p firmware=./firmware/rhino_pass.bin, tty_dbg=socat:./COM26,tty_bt=socat:./COM28
-g 23646
- TCP-порт, які будзе адкрыты для доступу да GDB-серверу;-n rhino
- імя асноўнага модуля сістэмы (прылада ў зборы);-l user
- імя бібліятэкі для пошуку асноўнага модуля;-y library
- шлях для пошуку модуляў, якія ўваходзяць у прыладу;firmwarerhino_pass.bin
- шлях да файла прашыўкі;- COM26 і COM28 – віртуальныя COM-парты.
У выніку будзе выведзена запрашэнне Python >
(Або Argparse >
):
18:07:59 INFO [eFactoryBuilder.create ]: Module top successfully created as top
18:07:59 INFO [ Module.initializeAndRes]: Setup core to top.u1_stm32.cortexm0.arm for top
18:07:59 INFO [ Module.initializeAndRes]: Setup debugger to top.u1_stm32.dbg for top
18:07:59 WARN [ Module.initializeAndRes]: Tracer wasn't found in top...
18:07:59 INFO [ Module.initializeAndRes]: Initializing ports and buses...
18:07:59 WARN [ Module.initializePortsA]: ATTENTION: Some ports has warning use printModulesPortsWarnings to see it...
18:07:59 FINE [ ARMv6CPU.reset ]: Set entry point address to 08006A75
18:07:59 INFO [ Module.initializeAndRes]: Module top is successfully initialized and reset as a top cell!
18:07:59 INFO [ Kopycat.open ]: Starting virtualization of board top[rhino] with arm[ARMv6Core]
18:07:59 INFO [ GDBServer.debuggerModule ]: Set new debugger module top.u1_stm32.dbg for GDB_SERVER(port=23946,alive=true)
Python >
Узаемадзеянне з IDA Pro
У якасці зыходнага файла для аналізу ў IDA для спрашчэння тэсціравання выкарыстоўваем прашыўку «Насарога» ў выглядзе
Вы таксама можаце выкарыстоўваць асноўную прашыўку без метаінфармацыі.
Пасля запуску Kopycat у IDA Pro у меню Debugger ідзем у пункт «Switch debugger…і выбіраемыRemote GDB debugger“. Далей наладжваем падлучэнне: меню Debugger – Process options…
Усталёўваны значэнні:
- Application - любое значэнне
- Hostname: 127.0.0.1 (ці IP-адрас выдаленай машыны, дзе запушчаны Kopycat)
- Порт: 23946
Цяпер становіцца даступная кнопка запуску адладкі (клавіша F9):
Націскаем яе - адбываецца падлучэнне да модуля адладчыка ў эмулятары. IDA пераходзіць у рэжым адладкі, становяцца даступныя дадатковыя вокны: інфармацыя аб рэгістрах, аб стэку.
Цяпер мы можам выкарыстоўваць усе стандартныя магчымасці працы з адладчыкам:
- пакрокавае выкананне інструкцый (Крок у и Пераступаць - клавішы F7 і F8, адпаведна);
- запуск і прыпыненне выканання;
- стварэнне кропак супыну як на код, так і на дадзеныя (клавіша F2).
Падлучэнне да адладчыка не азначае запуску кода прашыўкі. Бягучай пазіцыяй для выканання павінен быць адрас 0x08006A74
- пачатак функцыі Reset_Handler. Калі пракруціць лістынг ніжэй, то можна ўбачыць выклік функцыі асноўнай. Можна ўсталяваць курсор на гэтым радку (адрас 0x08006ABE
) і выканаць аперацыю Run until cursor (клавіша F4).
Далей можна націснуць F7, каб зайсці ў функцыю асноўнай.
Калі выканаць каманду Continue process (клавіша F9), то з'явіцца акно "Please wait" з адзінай кнопкай Прыпыняць:
Пры націску Прыпыняць выкананне кода прашыўкі прыпыняецца і можа быць працягнута з таго ж адраса ў кодзе, дзе было перапынена.
Калі працягнуць выкананне кода, то ў тэрміналах, падлучаных да віртуальных COM-партоў, можна ўбачыць наступныя радкі:
Наяўнасць радка "state bypass" кажа аб тым, што віртуальны Bluetooth-модуль перайшоў у рэжым прыёму дадзеных ад COM-порта карыстальніка.
Зараз у Bluetooth-тэрмінале (на малюнку - COM29) можна ўводзіць каманды ў адпаведнасці з пратаколам «Насарога». Напрыклад, на каманду "MEOW" у Bluetooth-тэрмінал вернецца радок "mur-mur":
Эмулюй мяне не цалкам
Пры пабудове эмулятара можна выбіраць ступень дэталізацыі/эмуляцыі той ці іншай прылады. Так, напрыклад, модуль Bluetooth можна эмуляваць па-рознаму:
- эмулюецца цалкам прылада з поўным наборам каманд;
- эмулююцца AT-каманды, а струмень дадзеных прымаецца з COM-порта асноўнай сістэмы;
- віртуальная прылада забяспечвае поўнае перанакіраванне дадзеных на рэальную прыладу;
- у выглядзе простай заглушкі, якая заўсёды вяртае "OK".
У бягучай версіі эмулятара выкарыстоўваецца другі падыход – віртуальны Bluetooth-модуль выконвае канфігураванне, пасля чаго пераходзіць у рэжым "праксіравання" дадзеных з COM-порта асноўнай сістэмы ў UART-порт эмулятара.
Разгледзім магчымасць простай інструментацыі кода ў выпадку, калі не рэалізавана нейкая частка перыферыі. Напрыклад, калі не створаны таймер, які адказвае за кантроль перадачы дадзеных у DMA (праверка выконваецца ў функцыі ws2812b_wait, размешчанай па адрасе 0x08006840
), то прашыўка будзе заўсёды чакаць скіду сцяга заняты, размешчанага па адрасе 0x200004C4
, які паказвае занятасць лініі дадзеных DMA:
Мы можам абысці такую сітуацыю шляхам «ручнога» скіду сцяга. заняты адразу пасля яго ўстаноўкі. У IDA Pro можна стварыць Python-функцыю і выклікаць яе ў breakpoint'е, пры гэтым сам breakpoint паставіць у кодзе пасля запісу значэння 1 у сцяг заняты.
Breakpoint-апрацоўшчык
Спачатку створым Python-функцыю ў IDA. Меню File - Script command…
Дадаем новы сниппет ў спісе злева, даём яму імя (напрыклад, БПТ),
у тэкставым полі справа ўводны код функцыі:
def skip_dma():
print "Skipping wait ws2812..."
value = Byte(0x200004C4)
if value == 1:
PatchDbgByte(0x200004C4, 0)
return False
Пасля гэтага націскаем прагон і закрываем акно скрыптоў.
Цяпер пяройдзем у код па адрасе 0x0800688A
, усталюем breakpoint (клавіша F2), адрэдагуем яго (кантэкснае меню Edit breakpoint…), не забудзем усталяваць тып скрыпту – Python:
Калі бягучае значэнне сцяга заняты роўна 1, то варта выканаць функцыю skip_dma у радку скрыптоў:
Калі запусціць прашыўку на выкананне, то спрацоўванне кода breakpoint-апрацоўшчыка можна ўбачыць у IDA у акне выхад па радку Skipping wait ws2812...
. Цяпер прашыўка не будзе чакаць скід сцяга заняты.
Узаемадзеянне з эмулятарам
Эмуляцыя дзеля эмуляцыі ці наўрад выкліча захапленне і радасць. Значна цікавей, калі эмулятар дапаможа даследніку ўбачыць дадзеныя ў памяці або ўсталяваць узаемадзеянне патокаў.
Пакажам, як у дынаміцы ўсталяваць узаемадзеянне RTOS-таскаў. Папярэдне трэба прыпыніць выкананне кода, калі яно запушчана. Калі перайсці ў функцыю bluetooth_task_entry у галіну апрацоўкі каманды «LED» (адрас 0x080057B8
), то можна ўбачыць, што спачатку ствараецца, а потым адпраўляецца ў сістэмную чаргу ledControlQueueHandle некаторае паведамленне.
Варта ўсталяваць breakpoint на зварот да зменнай ledControlQueueHandle, размешчанай па адрасе 0x20000624
і працягнуць выкананне кода:
У выніку спачатку адбудзецца прыпынак на адрас 0x080057CA
перад выклікам функцыі osMailAlloc, далей – па адрасе 0x08005806
перад выклікам функцыі osMailPut, потым праз некаторы час - па адрасе 0x08005BD4
(перад выклікам функцыі osMailGet), які належыць функцыі leds_task_entry (LED-таск), гэта значыць адбылося пераключэнне цягінаў, і зараз кіраванне атрымаў LED-таск.
Такім няхітрым спосабам можна ўсталяваць, як цягі RTOS узаемадзейнічаюць сябар з сябрам.
Вядома, у рэчаіснасці ўзаемадзеянне цягіц можа быць уладкована складаней, але з выкарыстаннем эмулятара адсочваць гэтае ўзаемадзеянне становіцца меней працаёмка.
Запуск з Radare2
Нельга абыйсці бокам такая ўніверсальная прылада як Radare2.
Для падлучэння да эмулятара з выкарыстаннем r2 каманда будзе выглядаць так:
radare2 -A -a arm -b 16 -d gdb://localhost:23946 rhino_fw42k6.elf
Цяпер даступныя запуск (dc
) і прыпыненне выканання (Ctrl+C).
Нажаль, на дадзены момант у r2 ёсць праблемы пры працы з хардварным gdb-серверам і разметкай памяці, з-за гэтага не працуюць кропкі супыну і Step'ы (каманда ds
). Спадзяемся, хуткім часам гэта будзе выпраўлена.
Запуск з Eclipse
Адзін з варыянтаў выкарыстання эмулятара - адладка прашыўкі распрацоўванай прылады. Для навочнасці будзем таксама выкарыстоўваць прашыўку «Насарога». Спампаваць зыходнікі прашыўкі можна
У якасці IDE будзем выкарыстоўваць Eclipse з набору
Для таго, каб у эмулятар загружалася прашыўка непасрэдна сабраная ў Eclipse, неабходна дадаць параметр firmware=null
у каманду запуску эмулятара:
binkopycat -g 23946 -n rhino -l user -y modules -p firmware=null,tty_dbg=COM26,tty_bt=COM28
Настройка debug-канфігурацыі
У Eclipse выбіраемы меню Run - Debug Configurations ... У якое адкрылася акне ў раздзеле GDB Hardware Debugging неабходна дадаць новую канфігурацыю, пасля чаго на ўкладцы «Main» пазначыць бягучы праект і дадатак для адладкі:
На ўкладцы "Debugger" неабходна пазначыць GDB-каманду:
${openstm32_compiler_path}arm-none-eabi-gdb
А таксама ўвесці параметры для падлучэння да GDB-серверу (хост і порт):
На ўкладцы "Startup" неабходна пазначыць наступныя параметры:
- уключыць галачку Загрузіць малюнак (каб выконвалася загрузка ў эмулятар сабранай выявы прашыўкі);
- уключыць галачку Load symbols;
- дадаць каманду запуску:
set $pc = *0x08000004
(выставіць у рэгістр PC значэнне з памяці па адрасе0x08000004
- там захоўваецца адрас ResetHandler'а).
Звярніце ўвагу, калі вы не хочаце загружаць файл прашыўкі з Eclipse, то параметры Загрузіць малюнак и Run commands паказваць не трэба.
Пасля націску Debug можна працаваць у рэжыме адладчыка:
- пакрокавае выкананне кода
- узаемадзеянне з кропкамі супыну
Заўвага. У Eclipse ёсць, хмм… некаторыя асаблівасці… і з імі даводзіцца жыць. Вось, напрыклад, калі пры запуску адладчыка з'явіцца паведамленне "No source available for "0x0"", то выканайце каманду Step (F5)
замест заключэння
Эмуляцыя натыўнага кода - справа вельмі цікавае. Для распрацоўніка прылад з'яўляецца магчымасць адладжваць прашыўку без рэальнай прылады. Для даследніка - магчымасць праводзіць дынамічны аналіз кода, што не заўсёды магчыма нават пры наяўнасці прылады.
Мы жадаем падаць адмыслоўцам прылада, які быў бы зручны, у меру просты і не адымаў шмат сіл і чакай на сваю наладу і запуск.
Напішыце ў каментарах аб сваім досведзе выкарыстання апаратных эмулятараў. Запрашаем да абмеркавання і будзем рады адказаць на пытанні.
Толькі зарэгістраваныя карыстачы могуць удзельнічаць у апытанні.
Для чаго Вы выкарыстоўваеце эмулятар?
-
распрацоўваю (адладжваю) прашыўкі
-
даследую прашыўкі
-
запускаю гульні (Dendi, Sega, PSP)
-
нешта іншае (напішыце ў каментары)
Прагаласавалі 7 карыстальнікаў. Устрымаліся 2 карыстальніка.
Які софт Вы карыстаецеся для эмуляцыі натыўнага кода?
-
QEMU
-
Unicorn engine
-
Пратэй
-
нешта іншае (напішыце ў каментары)
Прагаласавалі 6 карыстальнікаў. Устрымаліся 2 карыстальніка.
Што б Вам жадалася палепшыць у выкарыстоўваным эмулятары?
-
хочацца хуткасці
-
хочацца зручнасці наладкі / запуску
-
хочацца больш магчымасцяў узаемадзеяння з эмулятарам (API, хукі)
-
мяне ўсё задавальняе
-
нешта іншае (напішыце ў каментары)
Прагаласавалі 8 карыстальнікаў. Устрымаўся 1 карыстач.
Крыніца: habr.com