Как я могу узнать, что это делает?
-
19-09-2019 - |
Вопрос
Я получил этот фрагмент ассемблерного кода, извлеченный из какой-то программы, но, к сожалению, я ничего не знаю о ассемблере, а те фрагменты ассемблера, к которым я прикасался, остались в Commodore Amiga с 68000.
Кто-нибудь может подсказать мне, как я мог бы понять этот код без необходимости изучать ассемблер с нуля, или просто рассказать мне, что он делает?
Есть ли какой-нибудь "Симулятор", на котором я могу запустить это, чтобы посмотреть, что он делает?
-[ObjSample Param1:andParam2:]:
00000c79 pushl %ebp
00000c7a movl %esp,%ebp
00000c7c subl $0x48,%esp
00000c7f movl %ebx,0xf4(%ebp)
00000c82 movl %esi,0xf8(%ebp)
00000c85 movl %edi,0xfc(%ebp)
00000c88 calll 0x00000c8d
00000c8d popl %ebx
00000c8e cmpb $-[ObjSample delegate],_bDoOnce.26952-0xc8d(%ebx)
00000c95 jel 0x00000d47
00000c9b movb $-[ObjSample delegate],_bDoOnce.26952-0xc8d(%ebx)
00000ca2 movl 0x7dc0-0xc8d(%ebx),%eax
00000ca8 movl %eax,0x04(%esp)
00000cac movl 0x7df4-0xc8d(%ebx),%eax
00000cb2 movl %eax,(%esp)
00000cb5 calll _objc_msgSend
00000cba movl 0x7dbc-0xc8d(%ebx),%edx
00000cc0 movl %edx,0x04(%esp)
00000cc4 movl %eax,(%esp)
00000cc7 calll _objc_msgSend
00000ccc movl %eax,0xe4(%ebp)
00000ccf movl 0x7db8-0xc8d(%ebx),%eax
00000cd5 movl %eax,0x04(%esp)
00000cd9 movl 0xe4(%ebp),%eax
00000cdc movl %eax,(%esp)
00000cdf calll _objc_msgSend
00000ce4 leal (%eax,%eax),%edi
00000ce7 movl %edi,(%esp)
00000cea calll _malloc
00000cef movl %eax,%esi
00000cf1 movl %edi,0x08(%esp)
00000cf5 movl $-[ObjSample delegate],0x04(%esp)
00000cfd movl %eax,(%esp)
00000d00 calll _memset
00000d05 movl $0x00000004,0x10(%esp)
00000d0d movl %edi,0x0c(%esp)
00000d11 movl %esi,0x08(%esp)
00000d15 movl 0x7db4-0xc8d(%ebx),%eax
00000d1b movl %eax,0x04(%esp)
00000d1f movl 0xe4(%ebp),%eax
00000d22 movl %eax,(%esp)
00000d25 calll _objc_msgSend
00000d2a xorl %edx,%edx
00000d2c movl %edi,%eax
00000d2e shrl $0x03,%eax
00000d31 jmp 0x00000d34
00000d33 incl %edx
00000d34 cmpl %edx,%eax
00000d36 ja 0x00000d33
00000d38 movl %esi,(%esp)
00000d3b calll _free
00000d40 movb $0x01,_isAuthenticated-0xc8d(%ebx)
00000d47 movzbl _isAuthenticated-0xc8d(%ebx),%eax
00000d4e movl 0xf4(%ebp),%ebx
00000d51 movl 0xf8(%ebp),%esi
00000d54 movl 0xfc(%ebp),%edi
00000d57 leave
00000d58 ret
Решение
Это настраивает фрейм стека, выделяет 0x48 байт для локальных переменных и сохраняет ebx, esi и edi, это довольно стандартный функциональный пролог.
00000c79 pushl %ebp
00000c7a movl %esp,%ebp
00000c7c subl $0x48,%esp
00000c7f movl %ebx,0xf4(%ebp)
00000c82 movl %esi,0xf8(%ebp)
00000c85 movl %edi,0xfc(%ebp)
Это трюк ассемблера для того, чтобы настроить ebx так, чтобы он указывал на код, когда это будет сделано ebx содержит 00000c8d.
00000c88 calll 0x00000c8d
00000c8d popl %ebx
Этот бит гарантирует, что функция выполняется только один раз, если вы вызываете ее во второй раз, она просто переходит к концу (jel 0x00000d47)
00000c8e cmpb $-[ObjSample delegate],_bDoOnce.26952-0xc8d(%ebx)
00000c95 jel 0x00000d47
00000c9b movb $-[ObjSample delegate],_bDoOnce.26952-0xc8d(%ebx)
Этот бит копирует значения относительно ebx в локальное (стековое) пространство переменных, помните, что ebx указывает на текущую функцию, но смещения от ebx довольно велики.скорее всего, это постоянные данные, встроенные в код, и они настраиваются в качестве аргументов для вызова функции.
00000ca2 movl 0x7dc0-0xc8d(%ebx),%eax
00000ca8 movl %eax,0x04(%esp)
00000cac movl 0x7df4-0xc8d(%ebx),%eax
00000cb2 movl %eax,(%esp)
вызовите функцию.
00000cb5 calll _objc_msgSend
дополнительные постоянные значения, помещенные в стек, и еще один вызов той же функции, на этот раз возвращаемое значение вызова функции сохраняется в локальной переменной.:0xe4(%ebp)
00000cba movl 0x7dbc-0xc8d(%ebx),%edx
00000cc0 movl %edx,0x04(%esp)
00000cc4 movl %eax,(%esp)
00000cc7 calll _objc_msgSend
00000ccc movl %eax,0xe4(%ebp)
дополнительные значения, помещенные в стек для вызова функции, на этот раз одно значение является константой относительно ebx, а другое значение является возвращаемым значением из предыдущего вызова.
00000ccf movl 0x7db8-0xc8d(%ebx),%eax
00000cd5 movl %eax,0x04(%esp)
00000cd9 movl 0xe4(%ebp),%eax
00000cdc movl %eax,(%esp)
00000cdf calll _objc_msgSend
возьмите возвращаемое значение из этого вызова, удвоьте его и освободите столько памяти.
00000ce4 leal (%eax,%eax),%edi
00000ce7 movl %edi,(%esp)
00000cea calll _malloc
заполните память байтом, найденным в [ObjSample delegate]
00000cef movl %eax,%esi
00000cf1 movl %edi,0x08(%esp)
00000cf5 movl $-[ObjSample delegate],0x04(%esp)
00000cfd movl %eax,(%esp)
00000d00 calll _memset
отправьте еще одно сообщение, на этот раз с аргументами:0xe4(%ebp), константа из ebx, mallocd ptr, размер malloc, 4.Предположительно, это отправляет сообщение в наш буфер malloc'd, (буфер освобождается последним, а не возвращается вызывающему)
00000d05 movl $0x00000004,0x10(%esp)
00000d0d movl %edi,0x0c(%esp)
00000d11 movl %esi,0x08(%esp)
00000d15 movl 0x7db4-0xc8d(%ebx),%eax
00000d1b movl %eax,0x04(%esp)
00000d1f movl 0xe4(%ebp),%eax
00000d22 movl %eax,(%esp)
00000d25 calll _objc_msgSend
очистите edx и сохраните возвращаемое значение из вызова sendmessage в edi.
00000d2a xorl %edx,%edx
00000d2c movl %edi,%eax
eax >> 3
, тогда while (edx < eax) ++edx;
в этом нет особого смысла.
00000d2e shrl $0x03,%eax
00000d31 jmp 0x00000d34
00000d33 incl %edx
00000d34 cmpl %edx,%eax
00000d36 ja 0x00000d33
освободите память mallocd
00000d38 movl %esi,(%esp)
00000d3b calll _free
установите _isAuthenticated в значение true, также установите возвращаемое значение в значение true.похоже, что эта переменная присутствует в коде или, возможно, является глобальной.
00000d40 movb $0x01,_isAuthenticated-0xc8d(%ebx)
00000d47 movzbl _isAuthenticated-0xc8d(%ebx),%eax
восстановите регистры и вернитесь.
00000d4e movl 0xf4(%ebp),%ebx
00000d51 movl 0xf8(%ebp),%esi
00000d54 movl 0xfc(%ebp),%edi
00000d57 leave
00000d58 ret
Другие советы
Тяжелая работа...ваш ассемблер - это всего лишь подпрограмма, но он ссылается на другие подпрограммы и глобальные или статические переменные, поэтому лучшее, что мы можем сделать, - это иметь представление о его эквиваленте на более удобочитаемом языке.Но...давайте попробуем!(C-подобный язык)
int unknown_function(/* Parameters? */)
{
static char bDoOnce;
static char isAuthenticated;
uint32 tmp1,tmp2,tmp3;
void *p;
int i;
if (bDoOnce == ObjSample_delegate) {
return isAuthenticated;
}
bDoOnce = ObjSample_delegate;
tmp1= objc_msgSend(some_data1, some_data2);
tmp2 = objc_msgSend(tmp1, some_data3);
tmp3 = objc_msgSend(tmp2, some_data4);
p = malloc(tmp3*2);
memset(p, ObjSample_delegate, tmp3*2);
objc_msgSend(tmp2,some_data5,p, tmp3*2,4);
for (i = 0; i < tmp3/4; ++i) {
}
free(p);
isAuthenticated = 1;
return isAuthenticated;
}
Хм...недостаточно информации, чтобы выяснить, что происходит на самом деле (не говоря уже о том, что я, возможно, сделал что-то не так ;) ) Программа содержит слишком много "some_data", и пустой цикл for, похоже, здесь просто потребляет процессор .Хм...Является ли это функцией, скомпилированной gnu ObjectiveC?
Извините, я пытался, но я не могу сказать ничего более полезного.В любом случае, я надеюсь, что это сможет вам помочь.С уважением