Тимур, спасибо за очередную статью!
А это вдогонку
А это вдогонку
Создание консольных приложений в 64-разрядной Windows
Последнее редактирование:
Следуйте инструкциям в видео ниже, чтобы узнать, как установить наш сайт как веб-приложение на главный экран вашего устройства.
Примечание: Эта функция может быть недоступна в некоторых браузерах.
struct CHAR_INFO ;//<--- чтение/запись в экранный буфер консоли
UnicodeChar db 0 ;// символ в кодировке Юникод
AsciiChar db 0 ;// обычный символ Ascii
Attributes dw 0 ;// смотри ниже..
ends
;// запросить в EAX дескриптор вывода на консоль
invoke GetStdHandle,STD_OUTPUT_HANDLE
;// меняем атрибуты текста
invoke SetConsoleTextAttribute,eax, BACKGROUND_RED + FOREGROUND_YELLOW + FOREGROUND_INTENSITY
cinvoke printf, <10,' Press any key for exit...',0> ;// жёлтый на красном фоне
;// Устанавливает текущий размер и положение окна экранного буфера консоли
;// ***********************************************************************
BOOL SetConsoleWindowInfo ;// нуль = ошибка
hStdOutput dd 0 ;// дескриптор вывода
absCoords dd 0 ;// 1 = абсолютный (новый) размер, 0 = относительно текущего
lpSmallRect dd 0 ;// указатель на структуру SMALL_RECT -+
;// |
;// |
struct SMALL_RECT ;// <----------------------------------+
Left dw 0 ;// столбец(Х) верхнего/левого угла консоли
Top dw 0 ;// строка(Y) верхнего/левого угла
Right dw 0 ;// столбец(Х) нижнего/правого угла
Bottom dw 0 ;// строка(Y) нижнего/правого угла
ends
Замечание:
Функция SetConsoleWindowInfo() завершается ошибкой, если указанный прямоугольник окна выходит за границы экранного буфера консоли. Это означает, что элементы Top/Left не могут быть меньше нуля. Точно так же элементы Bottom/Right не могут быть больше, чем высота и ширина экранного буфера -1. Для консолей с более чем одним экранным буфером, изменение расположения окна для одного экранного буфера не влияет на расположение окон других экранных буферов.
.data
struct COORD
x dw 0 ;// горизонталь (столбцов)
y dw 0 ;// вертикаль (строк)
ends
struct SMALL_RECT
Left dw 0 ;// левый столбец,
Top dw 0 ;// ..и строка
Right dw 0 ;// правый столбец,
Bottom dw 0 ;// ..и строка
ends
.code
;// Меняем размер экранного буфера на 100х300
;//*********************************************
invoke GetStdHandle,STD_OUTPUT_HANDLE ;// EAX = дескриптор
mov [COORD.x],100 ;// символов в строке
mov [COORD.y],300 ;// строк в буфере
invoke SetConsoleScreenBufferSize,eax,dword[COORD]
;// Меняем размер окна консоли на 100х30
;//*********************************************
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [SMALL_RECT.Left] ,0
mov [SMALL_RECT.Top] ,0
mov [SMALL_RECT.Right] ,100-1 ;// отсчёт с нуля
mov [SMALL_RECT.Bottom], 30-1
invoke SetConsoleWindowInfo, eax, 1, SMALL_RECT
TRUE=1 при вызове функции говорит о том, что мы собираемся передать абсолютные координаты окна. Если-же указать FALSE=0, то можно просто прибавить требуемое кол-во строк и столбцов, относительно текущих значений – иногда это удобно и даже необходимо. Запрашивает эту инфу очередная функция GetConsoleScreenBufferInfo(), которая сбрасывает лог в одноимённую структуру с таким содержимым:struct CONSOLE_SCREEN_BUFFER_INFO
dwSize COORD ;// размер экранного буфера
dwCursorPosition COORD ;// текущая позиция курсора (резерв = 0)
wAttributes dw 0 ;// фон и цвет символов при вызове функции
szWindow SMALL_RECT ;// размер окна консоли
dwMaximumWindowSize COORD ;// макс.возможный размер окна
ends
;// Мотает часть буфера (или весь) выше/ниже
;// h = Handle, lp = указатель LongPointer, dw = значение DWORD
;//*********************************************************************
BOOL ScrollConsoleScreenBuffer ;//<--- Возвращает нуль при ошибке!
hStdout dd 0 ;// дескриптор вывода StdOut
lpScrollRect dd 0 ;// SMALL_RECT = прямоугольник, который необходимо переместить
lpClipRect dd 0 ;// SMALL_RECT = прямоугольник, на который влияет прокрутка
dwDestOrigin COORD ;// верхний/левый угол нового расположения ScrollRect
lpFill dd 0 ;// CHAR_INFO = символ, цвет символа/фона
lpScrollRect для нас в приоритете. В его структуре SMALL_RECT нужно указать координаты прямоугольника "Rectangle", на который будет действовать прокрутка "Scroll". В структуре-же второго аргумента lpClipRect определяются координаты всего, что осталось снаружи прокручиваемого фрейма, т.е. размер глобального экранного буфера – с этим аргументом можно вообще не заморачиваться, а просто выставить его в нуль.dwDestOrigin – его координаты x/y определяют, в какую сторону производить прокрутку буфера. Возможные варианты: вверх, вниз, влево, вправо. Если перевести дословно, то это "Destination", или адрес получателя. Ну и последний аргумент – указатель на структуру CHAR_INFO, в которую нужно будет предварительно поместить атрибут и символ для заполнения строки, освободившейся в результате скрола. Как-правило символом является пробел, чтобы родилась пустая строка под новую инфу. ;// Задаём размер активного прямоугольника.
;// Текущий размер окна и буфера = 100 колонок, и 30 строк.
;// Оставив слева 38 колонок и сверху 4 строки, будем прокручивать вверх остальные
;//********************************************************************************
mov [scrollRect.Left],38 ;// левый/верхний угол прямоугольника для скрола
mov [scrollRect.Top],4 ;// ...38=столбец(Х), 4=строка(Y)
mov [scrollRect.Right],100-1 ;// правый/нижний угол прямоугольника
mov [scrollRect.Bottom],23-1 ;// ...100=столбец(Х), 23=строка(Y)
mov [newPos.x],38 ;// новая позиция прямоугольника
mov [newPos.y],3 ;// 4-1 = 3 (сместить на одну строку вверх)
mov [charFill.Attributes],7 ;// атрибут символов = дефолт
mov [charFill.AsciiChar],' ' ;// символы новой строки (забивать пробелами)
invoke ScrollConsoleScreenBuffer,[StdOut],scrollRect,0,dword[newPos],charFill
struct PERFORMANCE_INFORMATION
cb dd sizeof.PERFORMANCE_INFORMATION
CommitTotal dd 0 ;// зарезервировано страниц
CommitLimit dd 0 ;// макс.зарезервировано
CommitPeak dd 0 ;// пик резервных страниц
PhysicalTotal dd 0 ;// всего физ.памяти в страницах
PhysicalAvailable dd 0 ;// доступно физ.памяти
SystemCache dd 0 ;// кэш-памяти в страницах
KernelTotal dd 0 ;// всего ядерной
KernelPaged dd 0 ;// выгружаемый пул ядра в страницах
KernelNonpaged dd 0 ;// невыгружаемый пул ядра
PageSize dd 0 ;// размер вирт.страницы в байтах
HandleCount dd 0 ;// всего дескрипторов
ProcessCount dd 0 ;// кол-во процессов в системе
ThreadCount dd 0 ;// общее кол-во потоков
ends
0...80000000h, а только в первоначальном кол-ве Commit. Дальше, если нам потребуется ещё, мы должны динамически запрашивать её у системы посредством VirtualAlloc(). Так-что при чтение последовательных адресов вполне можно нарваться на исключение 0xC0000005 = AccessViolation (нарушение прав доступа).format PE console
include 'win32ax.inc'
include 'equates\memory.inc'
include 'equates\console.inc'
entry start
;//-----------
.data
perfInfo PERFORMANCE_INFORMATION
buffInfo CONSOLE_SCREEN_BUFFER_INFO
conBuff COORD
curPos COORD
scrollRect SMALL_RECT
charFill CHAR_INFO
newPos COORD
StdIn dd 0
StdOut dd 0
speed dd 0
counter dd 0
nextOffs dd 0x00010000 ;//<----- нижний порог доступного юзеру адреса
mByte dd 1024*1024 ;// переменные для FPU
Result dq 0
pageSize dd 0
buff db 0
;//-----------
.code
start: invoke SetConsoleTitle,<'*** MemRead & Information ***',0>
;// Ставим свой обработчик исключений SEH
push DropException
push dword[fs:0]
mov dword[fs:0],esp
;// Берём в переменные дискрипторы ввода/вывода консоли
invoke GetStdHandle,STD_INPUT_HANDLE
mov [StdIn],eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov [StdOut],eax
;// Меняем размер консольного буфера
mov [conBuff.x],100
mov [conBuff.y],100
invoke SetConsoleScreenBufferSize,[StdOut],dword[conBuff]
;// Запрашиваем текущий размер окна, и подгоняем его под буфер
invoke GetConsoleScreenBufferInfo,[StdOut],buffInfo
mov esi,buffInfo.szWindow
mov word[esi+SMALL_RECT.Right],100-1
invoke SetConsoleWindowInfo,[StdOut],1,esi
;//*****************************************************************
;// Запрашиваем инфу о сис.памяти в структуру "perfInfo",
;// сохраняем размер вирт.страницы памяти, и инициализируем сопр FPU
invoke GetPerformanceInfo,perfInfo,sizeof.PERFORMANCE_INFORMATION
mov eax,[perfInfo.PageSize]
mov dword[pageSize],eax
finit
;// Выводим на консоль инфу о системной памяти (физ/вирт).
;// Функция возвращает её в страницах, поэтому переводим страницы в Мб.
push [perfInfo.PhysicalTotal]
call Page2Mbyte
cinvoke printf, <10,' SYSTEM MEMORY INFORMATION',\
10,' """"""""""""""""""""""""""""""',\
10,' Physical total...: %5.0f Mb',0>,dword[Result],dword[Result+4]
push [perfInfo.PhysicalAvailable]
call Page2Mbyte
cinvoke printf, <10,' Physical free....: %5.0f Mb',10,0>,dword[Result],dword[Result+4]
cinvoke printf, <10,' Virtual page size: %5d byte',0>,[perfInfo.PageSize]
push [perfInfo.CommitTotal]
call Page2Mbyte
cinvoke printf, <10,' Virtual current..: %5.0f Mb',0>,dword[Result],dword[Result+4]
push [perfInfo.CommitLimit]
call Page2Mbyte
cinvoke printf, <10,' Virtual limit....: %5.0f Mb',10,0>,dword[Result],dword[Result+4]
push [perfInfo.SystemCache]
call Page2Mbyte
cinvoke printf, <10,' System cache.....: %5.0f Mb',0>,dword[Result],dword[Result+4]
push [perfInfo.KernelTotal]
call Page2Mbyte
cinvoke printf, <10,' Kernel total.....: %5.0f Mb',0>,dword[Result],dword[Result+4]
push [perfInfo.KernelPaged]
call Page2Mbyte
cinvoke printf, <10,' Kernel paged.....: %5.0f Mb',0>,dword[Result],dword[Result+4]
push [perfInfo.KernelNonpaged]
call Page2Mbyte
cinvoke printf, <10,' Kernel nonpaged..: %5.0f Mb',10,0>,dword[Result],dword[Result+4]
cinvoke printf, <10,' Total process....: %5d',0>,[perfInfo.ProcessCount]
cinvoke printf, <10,' Total thread.....: %5d',0>,[perfInfo.ThreadCount]
cinvoke printf, <10,' Total handle.....: %5d',0>,[perfInfo.HandleCount]
;//*****************************************************************
;// Тест на чтение пользовательской памяти ОЗУ.
;// Запрашиваем скорость вывода дампа, и ставим счётчик "ошибок-доступа" к страницам.
cinvoke printf, <10,10,' """"""""""""""""""""""""""""""',\
10,' Type dump speed (0..500): ',0>
cinvoke scanf,<'%d',0>,speed
cinvoke printf, <' Page exception count....: 0',0>
invoke SetConsoleTextAttribute,[StdOut], BACKGROUND_RED + FOREGROUND_YELLOW + FOREGROUND_INTENSITY
cinvoke printf, <10,' Press space-key for exit....',0> ;// жёлтый на красном фоне
;// Тест на чтение пользовательской памяти ОЗУ
invoke SetConsoleTextAttribute,[StdOut], FOREGROUND_YELLOW + FOREGROUND_INTENSITY
invoke Sleep,1000
mov [curPos.x],38
mov [curPos.y],1
invoke SetConsoleCursorPosition,[StdOut],dword[curPos]
cinvoke printf,<'Offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ',0>
inc [curPos.y]
invoke SetConsoleCursorPosition,[StdOut],dword[curPos]
cinvoke printf,<'"""""""" """"""""""""""""""""""""""""""""""""""""""""""" ',0>
inc [curPos.y]
;// Цикл чтения и вывода памяти на консоль
@dump: call PrintMemoryString ;// распечатать 16-байт на консоль
add [nextOffs],16 ;// сместить указатель на сл.16-байт
invoke Sleep,[speed] ;// пауза, чтобы осмотреться
inc [curPos.y] ;// курсор на сл.строку
cmp [curPos.y],23 ;// проверить на нижнюю границу окна
jne @dump ;// повторить, если нет..
;// ИНАЧЕ:
;// Задаём размер прямоугольника для прокрутки
dec [curPos.y] ;// возвратить курсор на место (строка 23)
mov ax,[buffInfo.wAttributes] ;// берём атрибуты символа
mov [charFill.Attributes],ax ;// делаем их-же текущими для заполнения
mov [charFill.AsciiChar],' ' ;// символы новой строки (забивать пробелами)
mov [scrollRect.Left],38 ;// левый/верхний угол прямоугольника для скрола
mov [scrollRect.Top],4 ;// ...38=столбец(Х), 4=строка(Y)
mov [newPos.x],38 ;// новая позиция прямоугольника
mov [newPos.y],3 ;// ...4-1 = 3 (скрол на одну строку вверх)
mov [scrollRect.Right],100-1 ;// правый/нижний угол прямоугольника
mov [scrollRect.Bottom],23-1 ;// ...96=столбец(Х), 22=строка(Y)
;// Прокрутка буфера консоли =======================================
@scrollBuff:
mov eax,[nextOffs] ;// тест на чтение текущего адреса (SEH отловит ошибку)
invoke GetKeyState,VK_SPACE ;// проверить нажатие клавиши "пробел",
test eax,1 ;// ..для выхода из цикла прокрутки.
jnz @exit ;//
invoke ScrollConsoleScreenBuffer,[StdOut],scrollRect,0,dword[newPos],charFill
invoke SetConsoleCursorPosition,[StdOut],dword[curPos]
call PrintMemoryString ;// распечатать 16-байт на консоль
invoke Sleep,[speed] ;// пауза..
add [nextOffs],16 ;// сл.16-байт для вывода
cmp [nextOffs],0x7FFE0000 ;// тест на верхнюю границу юзерской памяти
jnz @scrollBuff ;// повторить, если не достигли её..
@exit: cinvoke getch
cinvoke exit,0
;//**** ВСПОМОГАТЕЛЬНЫЕ ПРОЦЕДУРЫ *****************************************************
;// При помощи FPU переводит кол-во страниц в Мегабайты
proc Page2Mbyte info
fild [info] ;// взять очередную инфу из struct "PERFORMANCE_INFORMATION"
fimul [pageSize] ;// умножить на размер вирт.страницы
fidiv [mByte] ;// перевести байты в Мбайты
fstp [Result] ;// сохранить результ в переменной!
ret
endp
;// Вывод дампа памяти на консоль
proc PrintMemoryString
invoke SetConsoleCursorPosition,[StdOut],dword[curPos]
mov esi,[nextOffs] ;// ESI = очередной адрес в памяти
push esi ;// +
cinvoke printf,<'%08X ',0>,esi ;// распечатать адрес!
pop esi ;// -
mov ecx,16 ;// кол-во байт в строке дампа (16 = параграф)
@str: xor eax,eax ;// EAX = 0
lodsb ;// AL = очередной байт из ESI
push esi ecx
cinvoke printf,<'%02x ',0>,eax ;// распечатать байт!
pop ecx esi
loop @str ;// повторить ECX-раз..
ret
endp
;// SEH - пользовательский обработчик исключений
proc DropException pRecord, pFrame, pContext, pParam
inc [counter] ;// считаем недоступные на R/W страницы
invoke SetConsoleCursorPosition,[StdOut],0x0015001b ;// курсор в статичную область буфера
cinvoke printf,<'%d'>,[counter] ;// вписать туда счётчик найденных страниц!
mov esi,[pContext] ;// ESI = указатель на контекст регистров
mov dword[esi+0xb8],@scrollBuff ;// 0xb8 = CONTEXT.RegEip (запись в EIP адреса перехода)
mov eax,[pageSize] ;// EAX = размер страницы вирт.памяти
add [nextOffs],eax ;// уйти на сл.страницу
cmp [nextOffs],0x7FFE0000 ;// тест на потолок юзера
jnz @f ;// пропустить, если не дошли до макс..
mov dword[esi+0xb8],@exit ;// иначе: регистр EIP = выход из программы
@@: xor eax,eax ;// возврат управления программе!!!
ret ;//
endp
;//**********************************************
section '.idata' import data readable
library kernel32,'kernel32.dll',user32,'user32.dll',\
msvcrt,'msvcrt.dll',psapi,'psapi.dll'
import msvcrt,printf,'printf',scanf,'scanf',getch,'_getch',exit,'exit'
import psapi, GetPerformanceInfo,'GetPerformanceInfo'
include 'api\kernel32.inc'
include 'api\user32.inc'
Статья читается полностью. Тезисы со ссылками на разделы появятся позже.
Это понятно, не сразу же оконные приложения писать. Оконные вызовы в основном нада знать для реверся имхо.Мое мнение, что именно после базового обучения программирования, то с этого и нужно начинать, а именно консоль, ее структуры и методы)))
Консоль - хакера и админа хлеб и сольБратья и сестры, здравы будьте!
Про консоль погуглить не забудьте:
Windows Command Reference pdf
Windows Command Line Administration Instant Reference pdf
Windows PowerShell 2.0. Справочник администратора pdf
Введение в Windows PowerShell pdf
Введение в C/C++ программирование консоли pdf
Основы программирования на C#. Консольные приложения pdf
И помните, консоль - юзера хлеб и соль.
Хакеры и деньги любят тишинуКонсоль - хакера и админа хлеб и соль![]()
COORD coord;[Alt+Enter] раскрывать консоль на весь экран
напомните, а как программно раскрывать консоль на весь экран?
Комментарии
13