Перейти к содержанию

Запись /чтение файла через ассемблер СЕ


Antonshka

Рекомендуемые сообщения

Привет всем!

У меня появилась необходимость записи и чтения файла через ассемблер СЕ.

Через Lua CE это делается либо через

writeRegionToFile
readRegionFromFile

либо через

io.open

Но я не могу использовать Lua потому что мне нужно производить запись или чтения файла именно в момент выполнения ассемблерной инструкции.

На данный момент знаю лишь то что для осуществления записи и чтения файла через ассемблер СЕ нужно предварительно подготовить необходимые для этого аргументы и вызвать метод CreateFileA

Спойлер

HANDLE CreateFileA(
  LPCSTR                lpFileName,
  DWORD                 dwDesiredAccess,
  DWORD                 dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD                 dwCreationDisposition,
  DWORD                 dwFlagsAndAttributes,
  HANDLE                hTemplateFile
);

 

а затем WriteFile

Спойлер

BOOL WriteFile(
  HANDLE       hFile,
  LPCVOID      lpBuffer,
  DWORD        nNumberOfBytesToWrite,
  LPDWORD      lpNumberOfBytesWritten,
  LPOVERLAPPED lpOverlapped
);

 

или ReadFile

Спойлер

BOOL ReadFile(
  HANDLE       hFile,
  LPVOID       lpBuffer,
  DWORD        nNumberOfBytesToRead,
  LPDWORD      lpNumberOfBytesRead,
  LPOVERLAPPED lpOverlapped
);

 

 

Но как это сделать через ассемблер СЕ я пока не понял. Именно, в какие регистры нужно записывать аргументы.

Есть мысль что можно попробовать собрать СЕ трейнер или С++ приложение с функцией записи и чтения файла. Затем отладить их через например СЕ. Но это пока только мысль.

 

Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Antonshka сказал:

Именно, в какие регистры нужно записывать аргументы.

Это функции WinAPI, они написаны по соглашению stdcall, то есть, все параметры нужно запихнуть в стек (в обратном порядке, то есть справа налево), и затем сделать вызов нужной функции.

Ссылка на комментарий
Поделиться на другие сайты

9 часов назад, Xipho сказал:

Это функции WinAPI, они написаны по соглашению stdcall, то есть, все параметры нужно запихнуть в стек (в обратном порядке, то есть справа налево), и затем сделать вызов нужной функции.

Спасибо за направление.

Прочитал про соглашения. Для 64 и 32 битных приложений способ передачи параметров оказался различный. Вот описание передачи параметров, если кому интересно.

 

Протестировал на 32 и 64 битных приложениях. Файл создается, хендл закрывается, все хорошо. Завтра допишу методы на запись и чтение.

В ходе экспериментов я наткнулся на одну интересную особенность. Объясните мне кто знает, почему так происходить. В 32 битном приложении, функция CreateFileA, после своего выполнения увеличивает ESP на количество переданных ей параметров умноженное на размер их типа (4 байта). То есть перед вызовом функции и после ее  вызова ESP разный. Тоже с функцией CloseHandle, в 32 разрядном приложении, ESP после выполнения больше на 4 (функция принимает один параметр). То есть функции увеличивают ESP автоматически.

В 64 битном приложении, RSP до и после вызова всегда одинаковый. Никакой автоматизации нет.

 

Это такая особенность которую нужно просто принять как должное? Где можно прочитать о ней?

Ссылка на комментарий
Поделиться на другие сайты

35 минут назад, Antonshka сказал:

В 64 битном приложении, RSP до и после вызова всегда одинаковый. Никакой автоматизации нет.

там статик стек, например:

testz:
struc .stack
resq 4
.5 resq 1
alignb 16
resq 1
endstruc
sub rsp,.stack_size
  
mov ecx,1
mov edx,2
mov r8d,3
mov r9d,4
mov dword[rsp+.5],5
call [xxxxxxxx]
  
mov ecx,1
call [xxxxx]

add rsp,.stack_size
ret

где .5 макс количество параметров апи

 

  • Понравилось 1
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, Antonshka сказал:

Для 64 и 32 битных приложений способ передачи параметров оказался различный.

Да, я забыл упомянуть про архитектуру

Ссылка на комментарий
Поделиться на другие сайты

14 часов назад, gmz сказал:

там статик стек, например:

Что делает твой пример кода? И что значит статик стек? Никак не пойму.

 

Нашел вот в описании соглашений для 64 (по той ссылке что выложил выше)

Спойлер

The x64 ABI considers registers RBX, RBP, RDI, RSI, RSP, R12, R13, R14, R15, and XMM6-XMM15 nonvolatile. They must be saved and restored by a function that uses them.

Поэтому регистр RSP неизменяется в 64 битном приложении до и после вызова функции? Потому что вызываемая функция должна восстановить его?

 

Запись/чтение из файла, если кому-нибудь понадобится. Тест проводился на СЕ туториал 64 бит

Запись

Спойлер

[ENABLE]
alloc(PLACEASM_Write_File_scr_1,2048,"Tutorial-x86_64.exe"+2B08C)
label(BACKASM_Write_File_scr_1)

alloc(FileName,1000)
registersymbol(FileName)
alloc(FileData,1000)
registersymbol(FileData)


PLACEASM_Write_File_scr_1:
pushfq
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push rbp
mov rbp,rsp
sub rsp,40
and rsp,fffffffffffffff0
//-------------- Create File
mov [rsp+30],0
mov [rsp+28],#128
mov [rsp+20],2
mov r9,0
mov r8,0
mov rdx,40000000
mov rcx,FileName
call CreateFileA
mov [rsp+38],rax // FileHandle
//---------------- Write To File
mov qword ptr [rsp+20],00000000
xor r9,r9
mov r8,#50 // Size
mov rdx,FileData
mov rcx,[rsp+38] // FileHandle
call WriteFile
//----------------- Close Handle
mov rcx,[rsp+38] // FileHandle
call CloseHandle
//------------------------
add rsp,40
mov rsp,rbp
pop rbp
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
popfq
//------------------------
sub [rbx+000007F0],eax
jmp BACKASM_Write_File_scr_1


///////////////////////////
FileName:
db 'D:\Myf111002.txt',0
FileData:
dd (float)1.554
///////////////////////////
"Tutorial-x86_64.exe"+2B08C:
jmp PLACEASM_Write_File_scr_1
nop
BACKASM_Write_File_scr_1:
[DISABLE]
dealloc(PLACEASM_Write_File_scr_1)
"Tutorial-x86_64.exe"+2B08C:
sub [rbx+000007F0],eax

{
// ORIGINAL CODE - INJECTION POINT: Tutorial-x86_64.exe+2B08C

Tutorial-x86_64.exe+2B060: 55                       - push rbp
Tutorial-x86_64.exe+2B061: 48 89 E5                 - mov rbp,rsp
Tutorial-x86_64.exe+2B064: 48 8D A4 24 D0 FE FF FF  - lea rsp,[rsp-00000130]
Tutorial-x86_64.exe+2B06C: 48 89 9D F0 FE FF FF     - mov [rbp-00000110],rbx
Tutorial-x86_64.exe+2B073: 48 89 CB                 - mov rbx,rcx
Tutorial-x86_64.exe+2B076: 48 C7 45 F8 00 00 00 00  - mov qword ptr [rbp-08],00000000
Tutorial-x86_64.exe+2B07E: 90                       - nop
Tutorial-x86_64.exe+2B07F: B9 05 00 00 00           - mov ecx,00000005
Tutorial-x86_64.exe+2B084: E8 D7 49 FE FF           - call Tutorial-x86_64.exe+FA60
Tutorial-x86_64.exe+2B089: 83 C0 01                 - add eax,01
// ---------- INJECTING HERE ----------
Tutorial-x86_64.exe+2B08C: 29 83 F0 07 00 00        - sub [rbx+000007F0],eax
// ---------- DONE INJECTING  ----------
Tutorial-x86_64.exe+2B092: 48 8D 4D F8              - lea rcx,[rbp-08]
Tutorial-x86_64.exe+2B096: E8 85 DD FD FF           - call Tutorial-x86_64.exe+8E20
Tutorial-x86_64.exe+2B09B: 8B 8B F0 07 00 00        - mov ecx,[rbx+000007F0]
Tutorial-x86_64.exe+2B0A1: 41 B9 FF 00 00 00        - mov r9d,000000FF
Tutorial-x86_64.exe+2B0A7: 4C 8D 85 F8 FE FF FF     - lea r8,[rbp-00000108]
Tutorial-x86_64.exe+2B0AE: 48 C7 C2 FF FF FF FF     - mov rdx,FFFFFFFFFFFFFFFF
Tutorial-x86_64.exe+2B0B5: 48 63 C9                 - movsxd  rcx,ecx
Tutorial-x86_64.exe+2B0B8: E8 E3 AE FD FF           - call Tutorial-x86_64.exe+5FA0
Tutorial-x86_64.exe+2B0BD: 45 31 C0                 - xor r8d,r8d
Tutorial-x86_64.exe+2B0C0: 48 8D 95 F8 FE FF FF     - lea rdx,[rbp-00000108]
}

 

Чтение

Спойлер

[ENABLE]
alloc(PLACEASM_Write_File_scr_1,2048,"Tutorial-x86_64.exe"+2B08C)
label(BACKASM_Write_File_scr_1)

alloc(FileSize,100)
registersymbol(FileSize)


PLACEASM_Write_File_scr_1:
pushfq
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
push rbp
mov rbp,rsp
sub rsp,40
and rsp,fffffffffffffff0
//-------------- Create File
mov [rsp+30],0
mov [rsp+28],#128
mov [rsp+20],3
mov r9,0
mov r8,0
mov rdx,80000000
mov rcx,FileName
call CreateFileA
mov [rsp+38],rax // FileHandle
//---------------- Get File Size
xor rdx,rdx
mov rcx,[rsp+38] // FileHandle
call GetFileSize
mov [FileSize],rax //FileSize
//---------------- Read From File
mov qword ptr [rsp+20],00000000
xor r9,r9
mov r8,[FileSize] // FileSize
mov rdx,FileData
mov rcx,[rsp+38] // FileHandle
call ReadFile
//----------------- Close Handle
mov rcx,[rsp+38] // FileHandle
call CloseHandle
//------------------------
add rsp,40
mov rsp,rbp
pop rbp
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
popfq
//------------------------
sub [rbx+000007F0],eax
jmp BACKASM_Write_File_scr_1


///////////////////////////
FileName:
db 'D:\Myf111002.txt',0
FileData:
dd (float)1.554
///////////////////////////
"Tutorial-x86_64.exe"+2B08C:
jmp PLACEASM_Write_File_scr_1
nop
BACKASM_Write_File_scr_1:
[DISABLE]
dealloc(PLACEASM_Write_File_scr_1)
"Tutorial-x86_64.exe"+2B08C:
sub [rbx+000007F0],eax

{
// ORIGINAL CODE - INJECTION POINT: Tutorial-x86_64.exe+2B08C

Tutorial-x86_64.exe+2B060: 55                       - push rbp
Tutorial-x86_64.exe+2B061: 48 89 E5                 - mov rbp,rsp
Tutorial-x86_64.exe+2B064: 48 8D A4 24 D0 FE FF FF  - lea rsp,[rsp-00000130]
Tutorial-x86_64.exe+2B06C: 48 89 9D F0 FE FF FF     - mov [rbp-00000110],rbx
Tutorial-x86_64.exe+2B073: 48 89 CB                 - mov rbx,rcx
Tutorial-x86_64.exe+2B076: 48 C7 45 F8 00 00 00 00  - mov qword ptr [rbp-08],00000000
Tutorial-x86_64.exe+2B07E: 90                       - nop
Tutorial-x86_64.exe+2B07F: B9 05 00 00 00           - mov ecx,00000005
Tutorial-x86_64.exe+2B084: E8 D7 49 FE FF           - call Tutorial-x86_64.exe+FA60
Tutorial-x86_64.exe+2B089: 83 C0 01                 - add eax,01
// ---------- INJECTING HERE ----------
Tutorial-x86_64.exe+2B08C: 29 83 F0 07 00 00        - sub [rbx+000007F0],eax
// ---------- DONE INJECTING  ----------
Tutorial-x86_64.exe+2B092: 48 8D 4D F8              - lea rcx,[rbp-08]
Tutorial-x86_64.exe+2B096: E8 85 DD FD FF           - call Tutorial-x86_64.exe+8E20
Tutorial-x86_64.exe+2B09B: 8B 8B F0 07 00 00        - mov ecx,[rbx+000007F0]
Tutorial-x86_64.exe+2B0A1: 41 B9 FF 00 00 00        - mov r9d,000000FF
Tutorial-x86_64.exe+2B0A7: 4C 8D 85 F8 FE FF FF     - lea r8,[rbp-00000108]
Tutorial-x86_64.exe+2B0AE: 48 C7 C2 FF FF FF FF     - mov rdx,FFFFFFFFFFFFFFFF
Tutorial-x86_64.exe+2B0B5: 48 63 C9                 - movsxd  rcx,ecx
Tutorial-x86_64.exe+2B0B8: E8 E3 AE FD FF           - call Tutorial-x86_64.exe+5FA0
Tutorial-x86_64.exe+2B0BD: 45 31 C0                 - xor r8d,r8d
Tutorial-x86_64.exe+2B0C0: 48 8D 95 F8 FE FF FF     - lea rdx,[rbp-00000108]
}

 

 

 

Изменено пользователем Antonshka
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

В 27.11.2020 в 08:13, Antonshka сказал:

Но я не могу использовать Lua потому что мне нужно производить запись или чтения файла именно в момент выполнения ассемблерной инструкции.

 

я такое делал при помощи функций дебаггера. Где-то на форуме видел тему про это и сделал по образцу. Выглядит как-то так:
 

Спойлер

changeregaddress=0x00a04f00
debug_removeBreakpoint(changeregaddress)
function toFile(s)
  fl = io.open("c:\file.txt","a+")
  fl:write(s.."\n")
  fl:close()
end

function debugger_onBreakpoint()
  if (EIP == changeregaddress) then
    hasChangedARegister=true
    st=readString(readPointer(ESP+0x4),200)
    toFile(st)
    changedEAX=true

    debug_continueFromBreakpoint(0)

    return 1
  else
    return 0
  end
end


debug_setBreakpoint(changeregaddress)
end


debug_setBreakpoint(changeregaddress)

 

 

Ссылка на комментарий
Поделиться на другие сайты

20 часов назад, youneuoy сказал:

я такое делал при помощи функций дебаггера. Где-то на форуме видел тему про это и сделал по образцу. Выглядит как-то так:
 

  Показать контент


changeregaddress=0x00a04f00
debug_removeBreakpoint(changeregaddress)
function toFile(s)
  fl = io.open("c:\file.txt","a+")
  fl:write(s.."\n")
  fl:close()
end

function debugger_onBreakpoint()
  if (EIP == changeregaddress) then
    hasChangedARegister=true
    st=readString(readPointer(ESP+0x4),200)
    toFile(st)
    changedEAX=true

    debug_continueFromBreakpoint(0)

    return 1
  else
    return 0
  end
end


debug_setBreakpoint(changeregaddress)
end


debug_setBreakpoint(changeregaddress)

 

 

Спасибо!

Но мне всё же WinAPI более пригляделся.

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.