ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2

ANTICHAT — форум по информационной безопасности, OSINT и технологиям

ANTICHAT — русскоязычное сообщество по безопасности, OSINT и программированию. Форум ранее работал на доменах antichat.ru, antichat.com и antichat.club, и теперь снова доступен на новом адресе — forum.antichat.xyz.
Форум восстановлен и продолжает развитие: доступны архивные темы, добавляются новые обсуждения и материалы.
⚠️ Старые аккаунты восстановить невозможно — необходимо зарегистрироваться заново.
Вернуться   Форум АНТИЧАТ > Программирование > Реверсинг
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Отладка программ, откомпилированных Visual C++. Часть 1.
  #1  
Старый 25.05.2009, 20:25
_=(mac)=_
Новичок
Регистрация: 28.02.2009
Сообщений: 9
Провел на форуме:
243438

Репутация: 19
Отправить сообщение для _=(mac)=_ с помощью ICQ
Lightbulb Отладка программ, откомпилированных Visual C++. Часть 1.

Дизассемблирование программ, откомпилированных Visual C++
Это моя первая статья, поэтому заранее прошу прощения за какие-либо неточности или ошибки))
Для начала напишем простенькую программу, которая принимает от нас два числа, затем складывает их, и выводит результат на экран.
Исходный текст нашей подопытной программы numberplus.cpp:

#include <iostream>
using namespace std;
int main()
{
int a, b, c;
cout <<"Enter number 1:\n";
cin >>a;
cout <<"Enter number 2:\n";
cin >>b;
c = a + b;
cout <<c;
}


Компилируем, на выходе получаем numberplus.exe и загружаем его в IDA Pro. OEP находится по адресу 0040A695, но мы переходим по адресу 00401000, по которому находится главная функция нашей программы.

Дизассемблерный листинг numberplus.exe


Код:
.text:00401000 sub_401000      proc near               ; CODE XREF: start-5C p
.text:00401000
.text:00401000 var_C           = dword ptr -0Ch	
.text:00401000 var_8           = dword ptr -8
.text:00401000 var_4           = dword ptr -4
.text:00401000                 ;Объявление локальных переменных
.text:00401000                 push    ebp
.text:00401001                 mov     ebp, esp
.text:00401003                 sub     esp, 0Ch
.text:00401003                 ;на этой стадии на дне стека сохраняем регистр ebp, копируем  esp .text:00401003                 ;в ebp, затем от esp вычитаем С. 
.text:00401006                 push    offset aEnterNumber1 ; "Enter number 1:\n"
.text:0040100B                 push    offset unk_423918
.text:00401010                 call    sub_4030D0
.text:00401010                 ; передача параметров и вызов функции вывода на экран. Первый параметр – смещение строки в сегменте данных, где находится строка для вывода, второй параметр – экземпляр объекта basic_istream, а затем собственно и сам call 
.text:00401015                 add     esp, 8
.text:00401015                 ;удаляем из стека переданные параметры
.text:00401018                 lea     eax, [ebp+var_4]
.text:0040101B                 push    eax
.text:0040101C                 mov     ecx, offset dword_42387C
.text:00401021                 call    sub_4013F0
.text:00401021                 ;в этом блоке мы в первую очередь заносим в eax указатель на буфер, где будет хранится первое число, потом идёт push eax, т.е. посылаем содержимое eax в стек в качестве параметра к функции ввода, затем кладём смещение basic_ostream в ecx… И сам вызов функции ввода
.text:00401026                 push    offset aEnterNumber2 ; "Enter number 2:\n"
.text:0040102B                 push    offset unk_423918
.text:00401030                 call    sub_4030D0
.text:00401030                 ; функция вывода на экран сообщения. Ничем не отличается от функции вывода, описанной выше, кроме смещения строки
.text:00401035                 add     esp, 8
.text:00401035                 ;выбрасываем из стека переданные параметры предъидущей функции
.text:00401038                 lea     ecx, [ebp+var_8]
.text:0040103B                 push    ecx
.text:0040103C                 mov     ecx, offset dword_42387C
.text:00401041                 call    sub_4013F0
.text:00401041                 ;ещё одна функция ввода, идентичная предъидущей
.text:00401046                 mov     edx, [ebp+var_4]
.text:00401049                 add     edx, [ebp+var_8]
.text:00401049                 ;что мы теперь имеем? Первое число, которое мы ввели, находится в ebp+var_4, второе в ebp+var_8. А в этом блоке мы первое число копируем в edx (mov edx,[ebp+var_4]), а второе мы складываем с edx, и заносим в этот же регистр(add edx, [ebp+var_8]).
.text:0040104C                 mov     [ebp+var_C], edx
.text:0040104C                 ; копируем содержимое edx  в ebp+var_C.
.text:0040104F                 mov     eax, [ebp+var_C]
.text:00401052                 push    eax
.text:00401053                 mov     ecx, offset unk_423918
.text:00401058                 call    sub_401070
text:00401058                 ;теперь осталось вывести сумму введённых нами чисел на экран. Тут мы копируем из ebp+var_C (кто не понял: тут хранится сумма наших чисел) число в eax, затем мы этот регистр кладём в стек в качестве параметра к функции вывода. 
.text:0040105D                 xor     eax, eax
.text:0040105F                 mov     esp, ebp
.text:00401061                 pop     ebp
.text:00401061                 ;обнуление eax, выравнивание стека…
.text:00401062                 retn
.text:00401062                 ;и выход
Из этого листинга видно, что данная функция отвечает за логику работы программы. Эта программа оперирует числами целого типа, и анализ такой программы довольно тривиальное занятие. Сейчас мы усложним немного программу, изменив в исходном коде тип переменных с целочисленных(int) на дробные(double). Изменяем, компилим, загружаем в Иду и видим:

Код:
.text:00401000 sub_401000      proc near               
.text:00401000 var_20          = qword ptr -20h	 
.text:00401000 var_18          = qword ptr -18h	
.text:00401000 var_10          = qword ptr -10h
.text:00401000 var_8           = qword ptr -8
.text:00401000
.text:00401000                 push    ebp
.text:00401001                 mov     ebp, esp
.text:00401003                 sub     esp, 18h 
.text:00401003                 ;отнимаем от регистра – указателя на вершину стека esp 18 байт 
.text:00401006                 push    offset aEnterNumber1 ; "Enter number 1:\n"
.text:0040100B                 push    offset unk_423918
.text:00401010                 call    sub_403070
.text:00401010                 ; передача функции вывода сообщения на экран параметров через стек. Первый параметр – адрес в сегменте данных, где находится эта строка, вторая – экземпляр объекта basic_istream, а call sub_403070 – вызов самой функции
.text:00401015                 add     esp, 8
.text:00401015                 ;удаляем из стека переданные параметры 
.text:00401018                 lea     eax, [ebp+var_8]
.text:0040101B                 push    eax
.text:0040101C                 mov     ecx, offset dword_42387C
.text:00401021                 call    sub_4013A0
.text:00401021                 ;Вызов функции ввода. Сначала кладём в eax указатель на буфер ввода, куда будет попадать число, которое мы введём, потом eax помещаем в стек, затем в ecx попадает экземпляр объекта basic_ostream, находящийся в памяти по адресу 42387С, затем идёт call sub_4013A0 – сам вызов функции ввода, которая ожидает 
ввода с клавиатуры в консоль числа
.text:00401026                 push    offset aEnterNumber2 ; "Enter number 2:\n"
.text:0040102B                 push    offset unk_423918
.text:00401030                 call    sub_403070
.text:00401030                 ;Функция вывода на экран. Первый параметр – строка, второй -  экземпляр объекта basic_istream, находящийся в 423918, а затем сам вызов функции
.text:00401035                 add     esp, 8
.text:00401035                 ;удаляем из стека переданные параметры(было передано 2 параметра предъидущей функции, каждая по 4 байта)
.text:00401038                 lea     ecx, [ebp+var_10]
.text:0040103B                 push    ecx
.text:0040103C                 mov     ecx, offset dword_42387C
.text:00401041                 call    sub_4013A0
.text:00401041                 ;функция ввода второго числа во второй буфер. lea ecx, [ebp+var_10] – в ecx после выполнения этой инструкции будет указатель на буфер, где будет храниться второе число. Затем мы ecx пересылаем в стек, после чего идёт call sub_4013A0 – функция ввода.	
.text:00401046                 fld     [ebp+var_8]	
.text:00401049                 fadd    [ebp+var_10]
.text:0040104C                 fstp    [ebp+var_18]
.text:0040104C                 ;а здесь начинается самое интересное.  Все числа в памяти, остались вычисления. Первая инструкция из буфера, где хранится первое число, которое мы ввели, копирует это число в регистр сопроцессора ST01. Вторая инструкция складывает второе число с ST0, следовательно в ST0 находится сумма чисел, которые мы ввели. Теперь дело за третьей инструкцией -  fstp [ebp+var_18], которая выполняет сразу две операции – перемещает наш результат из ST0 в ST7 и записывает его же в стек по указателю ebp+var_18
.text:0040104F                 sub     esp, 8
.text:0040104F                 ;отнимаем от esp 8 байт
.text:00401052                 fld     [ebp+var_18]
.text:00401052                 ;копируем результат вычисления из памяти по указателю ebp+var_18 в регистр ST0
.text:00401055                 fstp    [esp+20h+var_20]
.text:00401055                 ;перемещаем наш результат в ST7 и на вершину стека в качестве параметра к функции вывода нашего числа на экран. 
.text:00401058                 mov     ecx, offset unk_423918
.text:0040105D                 call    sub_401070
.text:0040105D                 ;сам вызов функции вывода 
.text:00401062                 xor     eax, eax
.text:00401062                 ;обнуление регистра eax
.text:00401064                 mov     esp, ebp
.text:00401064                 ; восстанавливаем регистр - указатель вершины стека 
.text:00401066                 pop     ebp
.text:00401066                 ;снимаем с верхушки стека значение, и заносим его в ebp
.text:00401067                 retn
.text:00401067                 ;конец
В этом примере мы более – менее разобрали работу с дробными числами. Из этого всего стоит сделать несколько выводов:
1. Операции с дробными числами выполняет сопроцессор
2. Дробные числа хранятся в специальном наборе регистров ST0 … ST7

Последний раз редактировалось _=(mac)=_; 26.05.2009 в 10:56..
 
Ответить с цитированием

  #2  
Старый 25.05.2009, 21:29
Balvan
Познающий
Регистрация: 11.03.2009
Сообщений: 70
Провел на форуме:
251358

Репутация: 6
По умолчанию

Молодец, продолжай! =)

Последний раз редактировалось Balvan; 25.05.2009 в 21:32..
 
Ответить с цитированием

  #3  
Старый 25.05.2009, 21:49
_=(mac)=_
Новичок
Регистрация: 28.02.2009
Сообщений: 9
Провел на форуме:
243438

Репутация: 19
Отправить сообщение для _=(mac)=_ с помощью ICQ
По умолчанию

Ха!!! А я то думал что говно полное))))))
 
Ответить с цитированием

  #4  
Старый 25.05.2009, 22:33
zeppe1in
Постоянный
Регистрация: 12.07.2006
Сообщений: 327
Провел на форуме:
1654818

Репутация: 117
По умолчанию

надо оформить получше, а то так читать не удобно
 
Ответить с цитированием

  #5  
Старый 25.05.2009, 23:53
_=(mac)=_
Новичок
Регистрация: 28.02.2009
Сообщений: 9
Провел на форуме:
243438

Репутация: 19
Отправить сообщение для _=(mac)=_ с помощью ICQ
По умолчанию

Вот блиин... Накосячил немного с оформлением( Извиняюсь и исправляю)))
 
Ответить с цитированием

  #6  
Старый 30.05.2009, 19:21
zeppe1in
Постоянный
Регистрация: 12.07.2006
Сообщений: 327
Провел на форуме:
1654818

Репутация: 117
По умолчанию

_=(mac)=_
и так вопросы)
как ты узнал адрес где находится главная функция программы?
и вот первый же call
Цитата:
Первый параметр – смещение строки в сегменте данных, где находится строка для вывода, второй параметр – экземпляр объекта basic_istream, а затем собственно и сам call
хорошо, указатель на строку я вижу.
а вот остальное совсем не понятно. пуш и кол собственно не о чом не говорят.
и что такое "экземпляр объекта" и зачем он нужен?)
 
Ответить с цитированием

  #7  
Старый 30.05.2009, 19:33
Lamia
Участник форума
Регистрация: 11.07.2007
Сообщений: 190
Провел на форуме:
254313

Репутация: 185
По умолчанию

Да лано придераться!Автор всё разжевал и в рот положил!Чего уж лучше!
 
Ответить с цитированием

  #8  
Старый 30.05.2009, 19:41
zeppe1in
Постоянный
Регистрация: 12.07.2006
Сообщений: 327
Провел на форуме:
1654818

Репутация: 117
По умолчанию

Lamia
я не придераюсь. я хочу научица юзать дизасемблер.
 
Ответить с цитированием

  #9  
Старый 30.05.2009, 19:49
Lamia
Участник форума
Регистрация: 11.07.2007
Сообщений: 190
Провел на форуме:
254313

Репутация: 185
По умолчанию

Шутка понята////
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
База Руссификаторы от KPOT_f!nd KPOT_f!nd Реверсинг 1 21.09.2006 21:06
«Лаборатории Касперского»: Количество вредоносных программ под Linux резко возросло dinar_007 Мировые новости 9 20.08.2006 20:50
С++ В трех вариациях... byte57 С/С++, C#, Delphi, .NET, Asm 30 30.12.2005 06:09
Пятая часть вредоносных программ в Windows XP - руткиты DRON-ANARCHY Мировые новости 0 14.12.2005 00:18



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ