eXeLab
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
обновлён 2 декабря!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Русский / Russian English / Английский

Сейчас на форуме: IsNull (+1 невидимый пользователь)
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS · SVN ·

 eXeL@B —› Программирование —› Программа под отладчиком работает не так как без отладчика. Магия?
Посл.ответ Сообщение

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 04:32 New!
Цитата · Личное сообщение · #1

Code:
  1. .386
  2. .model  flat, stdcall
  3. option  casemap:none
  4.  
  5. include    \masm32\include\windows.inc
  6. include    \masm32\include\kernel32.inc
  7. includelib \masm32\lib\user32.lib
  8. includelib \masm32\lib\kernel32.lib
  9.  
  10. GetFName proto
  11.  
  12. .data
  13. fHandle  DWORD ?
  14. stdout   DWORD ?
  15. cWritten DWORD ?
  16. error    BYTE  "Нет такого файла"
  17. noname   BYTE  "Укажите имя файла"
  18.  
  19. .code
  20. start:
  21.     main proc
  22.         invoke  GetStdHandle, STD_OUTPUT_HANDLE
  23.         mov     stdout, eax
  24.         invoke  GetFName
  25.         cmp     eax, -1
  26.         jz      empty
  27.         invoke  CreateFile,
  28.                 eax, 
  29.                 GENERIC_READ, 
  30.                 0,
  31.                 NULL,
  32.                 OPEN_EXISTING,
  33.                 FILE_ATTRIBUTE_NORMAL,
  34.                 0
  35.         cmp eax,INVALID_HANDLE_VALUE
  36.         jz  exit
  37.         mov     fHandle, eax
  38.         invoke  CloseHandle, fHandle
  39.         invoke  ExitProcess, 0
  40.     exit:
  41.         invoke  WriteConsoleA, stdout, ADDR error, sizeof error, ADDR cWritten, NULL
  42.         invoke  ExitProcess, 0
  43.     empty:
  44.         invoke  WriteConsoleA, stdout, ADDR noname, sizeof noname, ADDR cWritten, NULL
  45.         invoke  ExitProcess, 0
  46.     main endp
  47.  
  48.     GetFName proc
  49.         invoke  GetCommandLine
  50.         mov     edi, eax 
  51.         push    edi
  52.         mov     al, 0 
  53.         mov     ecx,-1 
  54.         cld
  55.         repne   scasb ;ищем нулевой символ, чтобы определить конец командной строки
  56.         not     ecx
  57.         pop     edi 
  58.         mov     al,20h 
  59.         repne   scasb ;ищем пробел, чтобы отделить параметр, переданный в командной строке
  60.         dec     edi               ;проверяем ..
  61.         cmp     byte ptr [edi],0  ;.. не ноль ли мы нашли вместо пробела
  62.         jz      empty ;.. если ноль, то параметра не было..
  63.         inc     edi ;.. если не ноль, то переходим к первому символу параметра
  64.         mov     eax,edi ;возвращаем адрес начала строки с параметром
  65.         ret
  66.     empty:
  67.         mov     eax,-1 
  68.         ret
  69.     GetFName endp
  70. end start

Прога запускается в консоли. Получает параметр. Если параметр не передать, то выводится "Укажите имя файла". Если параметр передан, то прога должна вывести "Нет такого файла" в том случае, если параметр не является именем существующего файла. Если же параметр является именем существующего файла, то никакого вывода не должно быть, прога просто отрабатывает и завершается.
Но! Если я не передаю параметр, то всё происходит правильно, и прога выдаёт "Укажите имя файла". А вот если я передаю ей параметр, то она в любом случае выдаёт "Нет такого файла", даже если параметр является именем существующего файла. Но если запустить прогу под отладчиком и передать правильный параметр, то она завершается правильно (если проследить за поиском строки, то видно, что название параметра обрабатывается верно, и в регистре EAX действительно передаётся верный адрес.. и прога переходит на нужную ветку исполнения, и завершается верно). В качестве отладчика использую OllyDbg.


Ранг: 540.1 (!)
Статус: Участник
_Вечный_Студент_

Создано: 27 марта 2016 06:42 New!
Цитата · Личное сообщение · #2

А как вы передаете параметер программе если она запущена под OllyDbg?

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 06:53 New!
Цитата · Личное сообщение · #3

plutos пишет:
А как вы передаете параметер программе если она запущена под OllyDbg?

Открываем OllyDbg, заходим в меню File -> Open. Выбираем нужную программу, а чуть ниже имени программы есть строчка Arguments.
На, а можно просто в консоли набрать "ollydbg programma.exe argument".


Ранг: 540.1 (!)
Статус: Участник
_Вечный_Студент_

Создано: 27 марта 2016 07:01 · Поправил: 27 марта 2016 07:23 plutos New!
Цитата · Личное сообщение · #4

Да, с параметрами в отладчике все правильно.

Хотел пробежаться по коду в той же ollyDbg, но меня почему-то AVG anti-virus на вашу программу сильно ругается:
Downloader Tibs Summary
Downloader Tibs is a malicious application that allows hackers to remotely access you computer system letting them modify files, steal personal information and install more unwanted software. These kinds of threats, called Trojan horse, must be sent to you by someone or carried by another program. They may also arrive thanks to unwanted downloads on infected websites or installed with online games or other internet-driven applications. Most Trojan horses can be detected and removed by AVG.

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 07:22 New!
Цитата · Личное сообщение · #5

plutos пишет:
но меня почему-то AVG anti-virus на вашу программу сильно ругается. У вас нет?

Я не пользуюсь антивирусами


Ранг: 540.1 (!)
Статус: Участник
_Вечный_Студент_

Создано: 27 марта 2016 07:47 · Поправил: 27 марта 2016 08:02 plutos New!
Цитата · Личное сообщение · #6

philimonix пишет:
выдаёт "Нет такого файла", даже если параметр является именем существующего файла


Добавьте вот такой код сразу после вызова CreateFile.
Может вы посылаете имя файла, который действительно существует, но что-то не срабатывает как надо в CreateFile.
Скажем, у одного процесса нет достаточных привилегий (to OPEN_EXISTING), а у другого есть, и т.д.
Ведь "под отладчиком" это один процесс, а "без отладчика" уже совсем другой.

Code:
  1. LOCAL   dwLastErr       :DWORD,
  2.             szError[1024]   :BYTE
  3.  
  4.     invoke GetLastError
  5.     mov dwLastErr,eax
  6.     invoke FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,0,dwLastErr,0,ADDR szError,1024,0
  7.     print str$(dwLastErr)," "
  8.     print ADDR szError,13,10
  9.  
  10.  

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 08:10 New!
Цитата · Личное сообщение · #7

plutos пишет:
Добавьте вот такой код сразу после вызова CreateFile.

Что-то много ругани от компилятора из-за этих строчек.

{ Атач доступен только для участников форума } - ругань.png

Ранг: 49.7 (посетитель)
Статус: Участник

Создано: 27 марта 2016 08:22 New!
Цитата · Личное сообщение · #8

philimonix, сделайте на си простейшую программу (можно и на MASM, просто на си короче и быстрее):
Code:
  1. void main(void)
  2. {
  3. printf("%s\n", GetCommandLine());
  4. return;
  5. }

Запустите её из-под CMD, а потом в отладчике, сразу увидите разницу.


Ранг: 540.1 (!)
Статус: Участник
_Вечный_Студент_

Создано: 27 марта 2016 08:37 · Поправил: 27 марта 2016 08:46 plutos New!
Цитата · Личное сообщение · #9

philimonix пишет:
Что-то много ругани от компилятора из-за этих строчек.


уберите директиву LOCAL и убедитесь, что эти две строчки

dwLastErr :DWORD,
szError[1024] :BYTE

находятся в секции .data.

Code:
  1. .data
  2. fHandle  DWORD ?
  3. stdout   DWORD ?
  4. cWritten DWORD ?
  5. error    BYTE  "Нет такого файла"
  6. noname   BYTE  "Укажите имя файла"
  7. dwLastErr DWORD,
  8. szError[1024] BYTE
  9.  

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 08:52 · Поправил: 27 марта 2016 08:53 philimonix New!
Цитата · Личное сообщение · #10

plutos пишет:
dwLastErr :DWORD,
szError[1024] :BYTE

На такие строчки тоже ругается.. Я вот так ещё попробовал:
Code:
  1. dwLastErr DWORD ?
  2. szError   BYTE 1024 dup (?)


.. тогда перестал ругаться на эти строчки и стал ругаться на print..

{ Атач доступен только для участников форума } - 123.png


Ранг: 540.1 (!)
Статус: Участник
_Вечный_Студент_

Создано: 27 марта 2016 09:17 · Поправил: 27 марта 2016 09:18 plutos New!
Цитата · Личное сообщение · #11

А что касается print, то можно обойтись и без нее (иначе мы еще больше запутаемся).

уберите 3 строчки
invoke FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,0,dwLastErr,0,ADDR szError,1024,0
print str$(dwLastErr)," "
print ADDR szError,13,10

и посмотрите, что будет в регистре eax после вызова GetLastError. Там должен быть код ошибки. потом посмотрите, какой именно ошибке этот код соответствует вот на этой странице:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 11:56 · Поправил: 27 марта 2016 12:21 philimonix New!
Цитата · Личное сообщение · #12

plutos пишет:
и посмотрите, что будет в регистре eax после вызова GetLastError. Там должен быть код ошибки.

Убрал всё непонятное, просто добавил вызов GetLastError() после вызова CreateFile(). В EAX оказался ноль. Я так понимаю, это означает, что CreateFile() отработала без нареканий. Специально потом вызвал программу с неправильным аргументом, тогда GetLastError поместила в EAX двойку, что значит "файл не найден". Получается, что CreateFile работает верно.

Ещё нюанс. Добавил вот такой код в секцию .data
Code:
  1. buf           db 32 dup(?)
  2. formatStr db "%d", 0

И вот такой код в секцию .code
Code:
  1. invoke  GetLastError
  2. invoke  wsprintf, ADDR buf, ADDR formatStr, eax
  3. invoke  WriteConsoleA, stdout, ADDR buf, 32, ADDR cWritten, NULL

В консоль выводится двойка, что означает "файл не найден", а если запускать в отладчике, то в EAX оказывается ноль.

Prober пишет:
Запустите её из-под CMD, а потом в отладчике, сразу увидите разницу.

Видимо, всё дело в том, что хоть программа одна и та же, но процессы разные.. получается, что одна и та же прога выполняется в разных контекстах, потому и результаты различны. Но, даже если так, хотелось бы всё-таки разобраться во всех нюансах. Если всё так, то тогда должна быть ошибка в коде, которая почему-то исправляется отладчиком.

Короче, я совсем уже запутался)))

Ранг: 409.7 (мудрец)
Статус: Участник

Создано: 27 марта 2016 12:20 · Поправил: 27 марта 2016 12:56 dosprog New!
Цитата · Личное сообщение · #13

philimonix пишет:
Короче, я совсем уже запутался)))


Не надо путаться.

Просто так неаккуратно разбор строки не делают. Это путь к трудноустранимым глюкам.
OllyDbg вставляет перед аргументом ОДИН символ пробела,
тогда как в реальности система вставляет ДВА символа пробела.
Отсюда и плясать.


Вот это будет работать, но название этому говнокод, уж сорри:
Code:
  1. .386
  2. .model  flat, stdcall
  3. option  casemap:none
  4.  
  5. include    \masm32\include\windows.inc
  6. include    \masm32\include\kernel32.inc
  7. includelib \masm32\lib\user32.lib
  8. includelib \masm32\lib\kernel32.lib
  9.  
  10. GetFName proto
  11.  
  12. .data
  13. fHandle  DWORD ?
  14. stdout   DWORD ?
  15. cWritten DWORD ?
  16. error    BYTE  "File not found"
  17. noname   BYTE  "Give me file name..."
  18.  
  19. sz_ok    BYTE  "Opened OK."
  20. fname   db 200h dup(?)
  21.  
  22. .code
  23. start:
  24.  
  25. main proc
  26.         invoke  GetStdHandle, STD_OUTPUT_HANDLE
  27.         mov     stdout, eax
  28.  
  29.         invoke  GetFName
  30.  
  31.         cmp     eax, -1
  32.         jz      empty
  33.  
  34.         invoke  CreateFile,
  35.                 eax, 
  36.                 GENERIC_READ, 
  37.                 0,
  38.                 NULL,
  39.                 OPEN_EXISTING,
  40.                 FILE_ATTRIBUTE_NORMAL,
  41.                 0
  42.         cmp eax,INVALID_HANDLE_VALUE
  43.         jz  exit
  44.  
  45.         invoke  WriteConsoleA, stdout, ADDR sz_ok, sizeof sz_ok, ADDR cWritten, NULL
  46.  
  47.         mov     fHandle, eax
  48.         invoke  CloseHandle, fHandle
  49.         invoke  ExitProcess, 0
  50.     exit:
  51.         invoke  WriteConsoleA, stdout, ADDR error, sizeof error, ADDR cWritten, NULL
  52.         invoke  ExitProcess, 0
  53.     empty:
  54.         invoke  WriteConsoleA, stdout, ADDR noname, sizeof noname, ADDR cWritten, NULL
  55.         invoke  ExitProcess, 0
  56. main endp
  57.  
  58.  
  59. GetFName proc
  60.         invoke  GetCommandLine
  61.         mov     edi, eax 
  62.  
  63.         push    edi 
  64.         mov     al, 0 
  65.         mov     ecx,-1 
  66.         cld
  67.         repne   scasb ;ищем нулевой символ, чтобы определить конец командной строки
  68.         not     ecx
  69.         pop     edi 
  70.  
  71.         mov     al,20h 
  72.         repne   scasb ;ищем пробел, чтобы отделить параметр, переданный в командной строке
  73.  
  74.         dec     edi               ;проверяем ..
  75.  
  76. @@eat_blanks:
  77.         inc edi
  78.         cmp byte ptr [edi],' '
  79.         jz @@eat_blanks
  80.         dec edi
  81.  
  82.         cmp     byte ptr [edi],0  ;.. не ноль ли мы нашли вместо пробела
  83.         jz      empty ;.. если ноль, то параметра не было..
  84.  
  85.         inc     edi ;.. если не ноль, то переходим к первому символу параметра
  86.         mov     eax,edi ;возвращаем адрес начала строки с параметром
  87.  
  88.         push  edi
  89.         mov esi,edi
  90.         mov edi,offset fname
  91.         xor eax,eax
  92. @@cp_next:
  93.         cld 
  94.         lodsb
  95.         stosw
  96.         dec edi
  97.         cmp al,0
  98.         jz @@cp_ok
  99.         cmp al,' '
  100.         jz @@cp_ok
  101.         cmp al,8
  102.         jz @@cp_ok
  103.         jmp @@cp_next
  104. @@cp_ok:
  105.         pop edi
  106.  
  107.         mov eax,offset fname
  108.  
  109.         ret
  110.     empty:
  111.         mov     eax,-1 
  112.         ret
  113.  
  114.     GetFName endp
  115. end start


Ото и вся магия..

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 12:36 New!
Цитата · Личное сообщение · #14

dosprog пишет:
Просто так неаккуратно разбор строки не делают. Это путь к трудноустранимым глюкам.

Это я уже понял)) Просто это пример из книги. А я такой человек, что если столкнулся с такой ерундой, то у меня всё зудит до тех пор пока не пойму в чём дело))
Забавненько)) Ваш код правильно работает в консоли, но неправильно под отладчиком)) Теперь всё наоборот) Но теперь уже видно, что отладчик "съедает" первый символ параметра.

Полегчало немного)) Спасибо))

Ранг: 409.7 (мудрец)
Статус: Участник

Создано: 27 марта 2016 12:38 · Поправил: 27 марта 2016 12:42 dosprog New!
Цитата · Личное сообщение · #15

philimonix пишет:
Это я уже понял)) Просто это пример из книги.


Тогда понятно. .

philimonix пишет:
что отладчик "съедает" первый символ параметра.

Программа кривая его съедает, а не отладчик..


philimonix пишет:
Ваш код правильно работает в консоли, но неправильно под отладчиком))


Поправил. Теперь всё в порядке в обоих случаях (сравнительно..)

Ранг: 488.4 (мудрец)
Статус: Участник

Создано: 27 марта 2016 12:40 New!
Цитата · Личное сообщение · #16

philimonix пишет:
Но теперь уже видно, что отладчик "съедает" первый символ параметра.

отладчики ничего не сьедают. это или руки кривые.. или понимание процесса отсутсвует.. все что может сьесть отладчик.. это эксепшены.

Ранг: 4.6 (гость)
Статус: Участник

Создано: 27 марта 2016 12:51 · Поправил: 28 марта 2016 06:28 philimonix New!
Цитата · Личное сообщение · #17

VodoleY пишет:
это или руки кривые.. или понимание процесса отсутсвует..

Ну, я только начинаю учиться)) Конечно же, понимание процесса пока оставляет желать лучшего. Но, думаю, это просто дело времени)

dosprog пишет:
Тогда понятно. .

Учебники с ошибками в исходниках ещё полезнее чем правильные и грамотные)) Пока ковыряешься с такой ерундой, поучаешь больше опыта и понимания, чем если бы разбирал сразу правильно написанные программы))

Добавлено спустя 17 часов 37 минут
Если кому интересно, есть ещё один вариант решения. Подсказали на другом форуме.
Процедура GetFName() ищет первый пробел в строке, хотя надо бы искать последний. И тогда никаких проблем не возникает.
Вот так надо переписать эту процедуру:
Code:
  1. GetFName proc
  2.         invoke  GetCommandLine
  3.         mov     edi, eax 
  4.         xor     eax,eax;al, 0
  5.         or     ecx,-1         
  6.         repne   scasb ;ищем нулевой символ, чтобы определить конец командной строки
  7.         not     ecx
  8.         mov     al,20h
  9.         std 
  10.         repne   scasb ;ищем последний пробел, чтобы отделить параметр, переданный в командной строке
  11.         add     edi,2
  12.         cld  
  13.         jecxz      empty ;.. если ноль, то параметра не было..
  14.         mov     eax,edi ;возвращаем адрес начала параметра
  15.         ret
  16.     empty:
  17.         or     eax,-1 
  18.         ret
  19.     GetFName endp

Ранг: 488.4 (мудрец)
Статус: Участник

Создано: 28 марта 2016 08:49 · Поправил: 28 марта 2016 08:51 VodoleY New!
Цитата · Личное сообщение · #18

philimonix встает вопрос.. отладчик тут причем? ошибки в коде не надо на дебагер валить
ЗЫ GetFName() .. вы не путайте теплое с мягким.. спецификацию 8+3 еще никто не отменял.. если вы путь к файлу в формате лонг нейм указываете.. будьте добры его в ковычки запердолить. и хватить бороться с мельницами

| Сообщение посчитали полезным: ajax


Ранг: 409.7 (мудрец)
Статус: Участник

Создано: 30 марта 2016 02:28 · Поправил: 30 марта 2016 04:44 dosprog New!
Цитата · Личное сообщение · #19

philimonix пишет:
Процедура GetFName() ищет первый пробел в строке, хотя надо бы искать последний.


См. фрагмент кода из прошлого поста, он этим и занимается:
Code:
  1. @@cp_next:


philimonix пишет:
Если кому интересно, есть ещё один вариант решения.


Не интересно, если честно.
Эта процедура однозначно не на десять строчек, такие костыльные варианты лучше не использовать.
Что могу порекомендовать - найти какую-то утиль, где нормально реализован разбор строки, и вынуть его оттуда.
Не надо изобретать - всё уже давно изобретено до нас, как написал VodoleY.

| Сообщение посчитали полезным: v00doo

 eXeL@B —› Программирование —› Программа под отладчиком работает не так как без отладчика. Магия?

Оригинальный DVD-ROM: eXeL@B DVD !

Вы находитесь на форуме сайта EXELAB.RU
Проект ReactOS