March and April MSDN Magazine HTML Help Files

Вышел апрельский номер MSDN Magazine.

Но по каким-то причинам на странице " MSDN Magazine HTML Help Files" ни апрельский, ни мартовский номер не доступен.

Но если составить link руками, то оказывается, что файлы там лежат:
MSDN Magazine March 2008 rus, eng
MSDN Magazine April 2008 rus, eng

UPD:
Обновилась страница  MSDN Magazine HTML Help Files и теперь на ней есть ссылки на все номера.

[WindDbg] Спаси сапёра – 3 или 0x29 байт, которые потрясли Winmine

В прошлый раз меня немного покритиковали за краткость, в этот раз попробую подробнее рассказывать.

Итак, продолжим помогать абстрактному сапёру бороться с минами. В этот раз я покажу, как не взорваться, даже если попали в мину.

Как обычно запускаем winmine.exe (из Windows XP) и отладчик WinDbg. Из отладчика аттачимся к процессу winmine.exe, для этого жмём F6 (или меню File-Attach to a Process…).

Если у вас не настроены отладочные символы, то при подключении к процессу winmine.exe в командном окне появится текст:
Symbol search path is: *** Invalid ***

Т.к. нам нужны отладочные символы, то нужно задать путь к ним. Это можно сделать с помощью команды .sympath (обязательно с точкой вначале, т.к. это мета-команда отладчика)
.sympath SRV*c:symbols*http://msdl.microsoft.com/download/symbols

Дальше нам нужно загрузить отладочные символы к себе в кеш (в данном случае в папку c:symbols). Следующая команда загружает файл с отладочной информацией только для winmine.exe (что позволяет сэкономить трафик):
.reload /f winmine.exe

Проверить, что отладочные символы загружены можно с помощью команды lm:
lm m winmine

Просмотреть отладочные символы можно с помощью команды x:
x winmine!*

В списке функций есть функция GameOver, что красноречиво говорит о её назначении.
0100347c winmine!GameOver = <no type information>

Давайте поставим точку останова на эту функцию и попробуем проиграть или выиграть. Точку останова (break point) можно задать с помощью команды bp:
bp winmine!GameOver

Посмотреть список точек останова можно с помощью команды bl (breakpoint list), а удалить с помощью команды bc (breakpoint clear)
0:001> bl
0 e 0100347c     0001 (0001)  0:**** winmine!GameOver

Дальше жмём F5 или вводим команду g для продолжения выполнения программы и начинаем играть. В первый раз я проиграю, а во второй раз выиграю. И посмотрю изменения в параметрах функции (если они конечно есть). После того как я проиграл, сработала точка останова и в командном окне появляется следующая информация:
Breakpoint 0 hit
eax=00000001 ebx=00000001 ecx=0006fcbc edx=77c49a94 esi=00000007 edi=00000000
eip=0100347c esp=0006fcf4 ebp=0006fd68 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
winmine!GameOver:
0100347c 83256451000100  and     dword ptr [winmine!fTimer (01005164)],0 ds:0023:01005164=00000001
здесь мы видим состояние регистров и следующую команду:
and winmine!fTimer,0

Уже видя эту команду можно решить, что мы в нужном месте, т.к. этой командой останавливается таймер, а таймер, скорее всего, два раза останавливать не будет. Следовательно, этот код выполняется как при проигрыше, так и при выигрыше и уже здесь решается, что показать на экране. Давайте это проверим, для этого посмотрим параметры переданные через стек. Для просмотра памяти существует несколько команд d*. Нам сейчас нужна команда dd (dump double-word values). dd esp – покажет нам адрес возврата и переданные в функцию параметры:
0:000> dd esp
0006fcf4  010035b0 00000000 00000000 00000200
0006fd04  0006fd68 00000001 010038b6 00000007

010035b0 в данном случае является адресом возврата, а следующее за ним занчение 00000000 – переданным параметром.

Теперь снова запущу программу на выполнение (F5) и попробую выиграть. Снова сработала точка остановки, и я ввожу команду просмотра стека dd esp
0:000> dd esp
0006fcf4  010035b0 00000001 00000000 00000200
0006fd04  0006fd68 00000001 010038b6 00000008

Мы видим, что адрес возврата (010035b0) тот же самый, а вот параметр изменился 00000001 вместо 00000000. Т.е. скорее всего это и есть параметр отвечающий за выигрыш/проигрыш. Можно это проверить, поменяем этот параметр на 0, запустим на выполнение и посмотрим что произойдёт:
0:000> eb esp + 4 0
0:000> dd esp
0006fcf4  010035b0 00000000 00000000 00000200

Проигрыш! Т.е. действительно от этого параметра всё и зависит. Следующие шаги наши будут такими: нужно сравнить найденный параметр с 0 и, если это так, то просто выйти из функции GameOver при этом сохранив целостность стека.

В данном случае мы воспользуемся обычной практикой перехвата функций. Т.е. мы сначала напишем свою функцию, при вызове GameOver передадим управление на неё, а затем она вернёт (или не вернёт) управление в функцию GameOver.

Прежде чем писать свою функцию нужно найти в приложении немного свободной памяти у которой атрибут защиты позволяет выполнять код. Проще всего не искать незадействованную память, а просто выделить память с уже необходимыми нам атрибутами защиты (PAGE_EXECUTE_READWRITE). Для выделения памяти в WinDbg есть команда .dvalloc (и команда .dvfree для освобождения памяти).

Т.к. в память выделяется блоками по 4 КБ, то нет смысла выделять меньше, хотя нам конечно не нужно так много памяти.

Выделяем память и запоминаем адрес:
0:001> .dvalloc 1000
Allocated 1000 bytes starting at 00910000

Если вдруг у вас в данный момент выполняется winmine то его в любой момент можно остановить с помощью клавиш Ctrl+Break (или меню Debug-Break).

Итак, у нас есть 4 КБ памяти начиная с адреса 0x00910000 (у вас этот адрес будет другим).

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

Приступим, сначала разместим сроку в Unicode формате, для этого воспользуемся командой eu
eu 00910000 "Тут мина, будьте аккуратней!"

Проверим:
du 00910000
00910000  "Тут мина, будьте аккуратней!"

После этого, немного отступив, пишем код, т.к. в нашем распоряжении целых 4 килобайта можно смело отступить от строки байт так на 256 (0x100).

Код следующий:
cmp dword ptr [esp+4],0 ; сравниваем параметр с 0
jne 91011a ; если не равен 0 то "прыгаем" на выигрышный код
push 0; начинаем помещать параметры для MessageBox в стек, флаг uType
push 0 ; параметр lpCaption
push 910000 ; параметр lpText, указываем адрес по которому находится наша строка
push 0 ; параметр hWnd, хендл окна, передаём 0
call USER32!MessageBoxW ; вызываем функцию
ret 4 ; очищаем 4 байта из стека и передаём управлении функции вызвавшей GameOver
91011a: метка начала "выигрышного" кода
and dword ptr [winmine!fTimer],0 ; останавливаем таймер
lea eax,[winmine!GameOver+0x7] ; в eax заносим адрес в функции GameOver
jmp eax ; передаём управление по этому адресу

А в начале функции GameOver нам нужно будет написать:
jmp 910100

Есть пара нюансов: т.к. мы перезаписываем код оригинальной функции GameOver, то нам нужно будет повторить его в своей функции, что и делается командой
and dword ptr [winmine!fTimer],0 ; останавливаем таймер
но это ещё не всё, код "and dword ptr [winmine!fTimer],0" занимает 7 байт (83256451000100), в то время как замещающий код "jmp 910100" занимает 5 байт (e97fcc90ff). Поэтому нам нужно затереть два байта оригинальной функции ничего не делающими инструкциями (например, nop, nop, или mov edi, edi), что бы процессор при исполнении эти два байта просто проскочил. А иначе он два байта, оставшиеся от предыдущей команды, попробует исполнить, и тогда всё закончится ошибкой. Т.е. вначале GameOver нужно написать:
jmp 910100
nop
nop

Запись ассемблерных инструкций производится командой a (assemble), дизассемблирование командой u (unassemble).

Приступим (00910000 нужно заменить на ваш адрес):
a 00910000 + 100
cmp dword ptr [esp+4],0
jne 0x00910000 + 0x11a
push 0
push 0
push 0x910000
push 0
call user32!MessageBoxW
ret 4
and dword ptr [winmine!fTimer],0
lea eax, [winmine!GameOver+0x7]
jmp eax

Для выхода из режима ввода ассемблерный инструкций нажмите ещё раз Enter. Теперь меняем функцию GameOver:
a winmine!GameOver
jmp 0x910000 + 0x100
nop
nop

Нажмите Enter ещё раз, для выхода из режима редактирования. Теперь очистите все точки останова с помощью команды bc * и нажмите F5 для продолжения выполнения программы и попробуйте проиграть 🙂

winmine02

В следующий раз покажу как получить Infinity Zoom в mspaint.

 

Tags: , .

[WinDbg] Спаси сапера – 2

Продолжим помогать сапёру в его нелегкой сапёрной жизни.
Сегодня покажу способ, описанный в замечательном блоге Debugging Toolbox.
1. Запускаем сапер;
2. запускаем WinDbg и аттачимся к winmine.exe;
3. переходим к процедуре winmine!StartGame и дизассемблируем её с помощью команды
0:001> u winmine!StartGame winmine!StartGame + 0n213
4. по смещению 0x53, от начала процедуры, виден вызов процедуры Rand, а чуть подальше ещё один
0:001> u winmine!StartGame + 0x53
winmine!StartGame+0x53:
010036cd e86e020000      call    winmine!Rnd (01003940)
010036d2 ff3538530001    push    dword ptr [winmine!yBoxMac (01005338)]
010036d8 8bf0            mov     esi,eax
010036da 46              inc     esi
010036db e860020000      call    winmine!Rnd (01003940)
именно в этом месте псевдо случайным образом определяется, в каких клетках будут находиться мины, а чуть пониже, по смещению 0x80, находится команда устанавливающая флаг присутствия бомбы в ячейке:
0:001> u winmine!StartGame + 0x80
010036fa 800880          or      byte ptr [eax],80h
5. к флагу присутствия бомбы добавим флаг её отображения:
0:001> eb winmine!StartGame + 80 c6 00 8a
0:001> u winmine!StartGame + 0x80
winmine!StartGame+0x80:
010036fa c6008a          mov     byte ptr [eax],8Ah
6. вводим команду g или просто жмём F5 и начинаем новую игру:

winmine01

У данного способа есть небольшой недостаток, можно промазать мимо пустой клетки и попасть в мину :), в следующий раз постараемся и этот недочёт исправить.

 

Tags: , .

А ваша сеть защищена?

Небезызвестная компания Secunia предлагает протестировать свою сеть на безопасность, а также протестить бету 1 новой версии сетевого софтверного инспектора (Secunia Network Software Inspector 2.0). Предложение ограничено по сроку: с 11-го по 30-ое апреля.
Рекомендую всем попробовать, уверен, найдёте в своей сети массу интересного 🙂
У кого нет сети – не расстраивайтесь, там же предлагается бесплатная персональная версия инспектора.

PS. На всякий случай уточню я к Secunia никакого отношения не имею (мопед не мой…), я за безопасность радею 🙂

 

Как с помощью netsh задать второй DNS сервер

Т.к. минут 10 потратил на поиск ответа на вопрос, решил здесь написать 🙂
Основной сервер можно задать с помощью команды:
netsh interface ipv4 set dnsserver "Interface Name" static XXX.XXX.XXX.XXX none
А задать второй DNS не получалось, пробовал сервер указывать через точку с запятой, просто через запятую. Ничего не выходило.
В конце концов, нашел, что нужно не set писать, а add:
netsh interface ipv4 add dnsserver "local area connection" XXX.XXX.XXX.XXX
С одной стороны логично ("добавить", вместо "задать"), но с другой стороны я обычно задаю два сервера и забываю об этом.

PS. Для netsh жутко не хватает CISCO like консоли.

«Играем» с помощью WinDBG

Недавно читал доклад про Windows Debugging Tools, а в качестве некоторых примеров показывал отладку Windows игр (сапер, freecell).
Все примеры проводились на Windows XP версиях программ

Пример 1, бесконечное время у сапера.

  • Настраиваем отладочные символы (описано в статье http://support.microsoft.com/kb/311503);
  • запускаем winmine.exe;
  • запускаем windbg.exe, жмём F6 (Attach to Process…), находим winmine.exe  и жмём ОК;
  • с помощью команды "x winmine!*" принудительно загружаем отладочные символы, попутно смотрим что есть, нас интересует функция winmine!DoTimer
  • с помощью команды "u winmine!DoTimer winmine!DoTimer + 28" показываем дизассемблированный код функции
    0:001> u winmine!DoTimer winmine!DoTimer + 28
    winmine!DoTimer:
    01002fe0 833d6451000100  cmp     dword ptr [winmine!fTimer (01005164)],0
    01002fe7 741e            je      winmine!DoTimer+0x27 (01003007)
    01002fe9 813d9c570001e7030000 cmp dword ptr [winmine!cSec (0100579c)],3E7h
    01002ff3 7d12            jge     winmine!DoTimer+0x27 (01003007)
    01002ff5 ff059c570001    inc     dword ptr [winmine!cSec (0100579c)]
    01002ffb e8b5f8ffff      call    winmine!DisplayTime (010028b5)
    01003000 6a01            push    1
    01003002 e8e6080000      call    winmine!PlayTune (010038ed)
    01003007 c3              ret

    видим, что за увеличение таймера отвечает переменная winmine!cSec. Дальше есть два варианта: 1) можно время от времени "брякать" winmine (Ctrl+Break) и задавать нужное значение с помощью команды"eb winmine!cSec XX", где XX нужное количество секунд; 2) можно просто пропатчить код сапера, что бы он не увеличивал время, делаем это с помощью команды "eb winmine!DoTimer + 15 90 90 90 90 90 90".
  • Жмём F5 (или вводим команду "g") и наслаждаемся игрой.

winmine00

 

Остальные примеры опишу позже.

PS. Презентацию и материалы к докладу можно найти на сайте http://mgupi.ineta.ru/

Tags: .

Hyper-V в Windows Vista x86 :)

При отладке ядра Windows Vista x86 SP1 наткнулся на обращения к функциям работающими с Hyper-V.
kd> k
ChildEBP RetAddr 
817a2b5c 81dc93e7 nt!HvlpTryConnectHypervisor+0x28a
817a2cf0 81d56ed3 nt!InitBootProcessor+0x38b
817a2d3c 81797321 nt!KiInitializeKernel+0x65b
00000000 00000000 nt!KiSystemStartup+0x319

Правда, скорее всего, нигде нет Hyper-V скомпилированного под 32-ух битную платформу.