Monday, August 17, 2009

Diana Dasm

Дошли руки стартовать небольшой проект на sourceforge: Diana Disassembler.
Цель проекта - иметь под рукой максимально удобный, переносимый и быстрый инструмент для получения доступа к интересным частям ядра.
Важные для меня вкусности:
  • ядро написано на чистом C, никаких dll, OS-зависимых частей, минимальные требования к рантайму;
  • часть ядра сгенерирована автоматически из Intel'овской спецификации (в два этапа html->xml->diana_gen.c);
  • данные для дизассемблирования передаются через С-style streams;
  • код покрыт юнит тестами;
Недостатки:
  • маловато комментариев и документации;
  • пока нет поддержки x64;
  • 16 bit режим есть, но тестами пока не покрыт;
  • не поддерживаются всякие расширения: FPU, SIMD, MMX - не было необходимости, пока;
Код написан в свободное от основной работы время, и выложен под BSD лицензией, вдруг кому еще пригодится.
Пример использования:
/* TEST 1

8195e9d7 f00fb116 lock cmpxchg [esi],edx
81881dc5 c1e902 shr ecx,0x2
81881db0 f3a5 rep movsd
*/


unsigned char buf[] = {0xf0, 0x0f, 0xb1, 0x16,
0xc1, 0xe9, 0x02,
0xf3, 0xa5};


DianaParserResult result;
DianaGroupInfo * pGroupInfo = 0;
size_t cmdSize = 0;
int iRes = 0;

DianaContext context;
DianaMemoryStream stream;

Diana_InitContext(&context, DIANA_MODE32);

// init stream over memory
Diana_InitMemoryStream(&stream, buf, sizeof(buf));

iRes = Diana_ParseCmd(&context,
Diana_GetRootLine(), // all database
&stream.parent, // OOP in C :)
&result);
cmdSize = stream.curSize - context.iReadedSize;

TEST_ASSERT_IF(!iRes)
{
TEST_ASSERT(result.iLinkedOpCount==2);
TEST_ASSERT(result.pInfo->m_operandCount ==2);
TEST_ASSERT(pGroupInfo = Diana_GetGroupInfo(result.pInfo->m_lGroupId));
TEST_ASSERT(strcmp(pGroupInfo->m_pName, "cmpxchg")==0);
TEST_ASSERT(result.linkedOperands[0].type == diana_index);
TEST_ASSERT(result.linkedOperands[0].value.rmIndex.seg_reg == reg_DS);
TEST_ASSERT(result.linkedOperands[0].value.rmIndex.reg == reg_ESI);
TEST_ASSERT(result.linkedOperands[0].value.rmIndex.indexed_reg == reg_none);
TEST_ASSERT(result.linkedOperands[0].value.rmIndex.index == 0);
TEST_ASSERT(result.linkedOperands[0].value.rmIndex.dispSize == 0);
TEST_ASSERT(result.linkedOperands[0].value.rmIndex.dispValue == 0);

TEST_ASSERT(result.linkedOperands[1].type == diana_register);
TEST_ASSERT(result.linkedOperands[1].value.recognizedRegister == reg_EDX);

TEST_ASSERT(result.iPrefix == DI_PREFIX_LOCK);
}
_Winnie C++ Colorizer

No comments: