xd
This commit is contained in:
Eren
2024-11-14 23:30:43 +03:00
committed by GitHub
commit 9742c47cb7
5 changed files with 1392 additions and 0 deletions
+340
View File
@@ -0,0 +1,340 @@
section .data
FILENAME_SIZE equ 256
section .bss
bar_num_files resw 1
bar_file_size resd 1
bar_bytes_remaining resd 1
bar_filename_buffer resb FILENAME_SIZE
bar_temp_filename resb FILENAME_SIZE
bar_check1 resd 1
bar_check2 resd 1
bar_current_dir resb 260
section .text
extract_bar:
push ebp
mov ebp, esp
push 0
push bytes_read
push 10
push header_buffer
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz cleanup
push 0
push bytes_read
push 2
push bar_num_files
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz cleanup
bar_extract_loop:
movzx ecx, word [bar_num_files]
test ecx, ecx
jz cleanup
push 0
push bytes_read
push FILENAME_SIZE
push bar_filename_buffer
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz cleanup
call bar_process_filename
push 0
push bytes_read
push 8
push bar_check1
push dword [file_handle]
call _ReadFile@20
call bar_read_file_size
test eax, eax
jz cleanup
call bar_create_output_path
call bar_extract_file_data
test eax, eax
jz cleanup
dec word [bar_num_files]
jmp bar_extract_loop
.invalid_format:
push 0
push bytes_written
push msg_invalid_bar_len
push msg_invalid_bar
push dword [stdout_handle]
call _WriteFile@20
jmp cleanup
bar_process_filename:
push ebp
mov ebp, esp
mov al, [bar_filename_buffer + FILENAME_SIZE - 1]
cmp al, 0xFE
je .fe_format
mov esi, bar_filename_buffer
mov edi, bar_temp_filename
mov ecx, FILENAME_SIZE - 4
rep movsb
mov byte [edi], 0
push FILE_CURRENT
push 0
push -4
push dword [file_handle]
call _SetFilePointer@16
cmp eax, 0xFFFFFFFF
je .error
jmp .clean_filename
.fe_format:
mov esi, bar_filename_buffer
mov edi, bar_temp_filename
.find_fe:
lodsb
cmp al, 0xFE
je .fe_found
stosb
cmp esi, bar_filename_buffer + FILENAME_SIZE
jb .find_fe
.fe_found:
mov byte [edi], 0
.clean_filename:
mov edi, bar_temp_filename
xor edx, edx
.trim_loop:
mov al, [edi]
test al, al
jz .trim_done
cmp al, ' '
je .next_trim
cmp al, '.'
je .next_trim
cmp al, 9
je .next_trim
cmp al, 13
je .next_trim
cmp al, 10
je .next_trim
mov edx, edi
.next_trim:
inc edi
cmp edi, bar_temp_filename + FILENAME_SIZE
jb .trim_loop
.trim_done:
mov edi, edx
inc edi
mov byte [edi], 0
mov edi, bar_temp_filename
.convert_slashes:
mov al, [edi]
test al, al
jz .done
cmp al, '\\'
jne .next_char
mov byte [edi], '/'
.next_char:
inc edi
jmp .convert_slashes
.done:
mov esp, ebp
pop ebp
ret
.error:
mov esp, ebp
pop ebp
ret
bar_read_file_size:
push ebp
mov ebp, esp
push 0
push bytes_read
push 4
push bar_file_size
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .error
push 0
push bytes_read
push 4
push bar_check1
push dword [file_handle]
call _ReadFile@20
mov esp, ebp
pop ebp
ret
.error:
mov esp, ebp
pop ebp
ret
bar_create_output_path:
push ebp
mov ebp, esp
mov esi, input_file
mov edi, output_path
.copy_path:
lodsb
stosb
test al, al
jnz .copy_path
dec edi
mov esi, extract_suffix
mov ecx, extract_suffix_len
rep movsb
mov byte [edi], '/'
inc edi
mov esi, bar_temp_filename
.copy_name:
lodsb
test al, al
jz .done
stosb
jmp .copy_name
.done:
mov byte [edi], 0
mov esi, output_path
mov edi, bar_current_dir
.create_dirs:
lodsb
stosb
test al, al
jz .dirs_done
cmp al, '/'
jne .create_dirs
mov byte [edi-1], 0
push eax
push 0
push bar_current_dir
call _CreateDirectoryA@8
pop eax
mov byte [edi-1], '/'
jmp .create_dirs
.dirs_done:
mov esp, ebp
pop ebp
ret
bar_extract_file_data:
push ebp
mov ebp, esp
push 0
push bytes_written
push msg_extract_len
push msg_extract
push dword [stdout_handle]
call _WriteFile@20
mov esi, output_path
call string_length
push 0
push bytes_written
push eax
push output_path
push dword [stdout_handle]
call _WriteFile@20
push 0
push bytes_written
push msg_newline_len
push msg_newline
push dword [stdout_handle]
call _WriteFile@20
push 0
push FILE_ATTRIBUTE_NORMAL
push CREATE_ALWAYS
push 0
push 0
push GENERIC_WRITE
push output_path
call _CreateFileA@28
cmp eax, INVALID_HANDLE_VALUE
je .error
mov ebx, eax
mov ecx, [bar_file_size]
mov [bar_bytes_remaining], ecx
.copy_loop:
mov eax, CHUNK_SIZE
cmp [bar_bytes_remaining], eax
jb .last_chunk
jmp .do_copy
.last_chunk:
mov eax, [bar_bytes_remaining]
.do_copy:
push 0
push bytes_read
push eax
push chunk_buffer
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .error
push 0
push bytes_written
push dword [bytes_read]
push chunk_buffer
push ebx
call _WriteFile@20
test eax, eax
jz .error
mov eax, [bytes_read]
sub [bar_bytes_remaining], eax
jnz .copy_loop
push ebx
call _CloseHandle@4
mov eax, 1
jmp .done
.error:
push ebx
call _CloseHandle@4
xor eax, eax
.done:
mov esp, ebp
pop ebp
ret
+256
View File
@@ -0,0 +1,256 @@
section .data
d2_flag_value db 1
section .bss
d2_num_files resd 1
d2_file_count resd 1
d2_path_len resd 1
d2_file_size resd 1
d2_flag resb 1
d2_path_buffer resb 1024
section .text
extract_d2:
push ebp
mov ebp, esp
push 0
push bytes_read
push 4
push d2_num_files
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
push FILE_CURRENT
push 0
push 4
push dword [file_handle]
call _SetFilePointer@16
mov eax, [d2_num_files]
mov [d2_file_count], eax
.process_files:
mov eax, [d2_file_count]
test eax, eax
jz .done
push 0
push bytes_read
push 1
push d2_flag
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
mov al, [d2_flag]
cmp al, [d2_flag_value]
jne .done
push 0
push bytes_read
push 4
push d2_path_len
push dword [file_handle]
call _ReadFile@20
push 0
push bytes_read
push 4
push d2_file_size
push dword [file_handle]
call _ReadFile@20
push FILE_CURRENT
push 0
push 16
push dword [file_handle]
call _SetFilePointer@16
mov eax, [d2_path_len]
push 0
push bytes_read
push eax
push d2_path_buffer
push dword [file_handle]
call _ReadFile@20
mov edi, d2_path_buffer
add edi, [d2_path_len]
mov byte [edi], 0
mov esi, d2_path_buffer
mov ecx, [d2_path_len]
.convert_slashes:
mov al, [esi]
cmp al, '\'
jne .next_char
mov byte [esi], '/'
.next_char:
inc esi
loop .convert_slashes
call create_d2_path
call extract_d2_file
dec dword [d2_file_count]
jmp .process_files
.done:
mov esp, ebp
pop ebp
jmp cleanup
create_d2_path:
push ebp
mov ebp, esp
mov esi, input_file
mov edi, output_path
.copy_base:
lodsb
stosb
test al, al
jnz .copy_base
dec edi
mov esi, extract_suffix
mov ecx, extract_suffix_len
rep movsb
mov byte [edi], '/'
inc edi
mov esi, d2_path_buffer
.copy_name:
lodsb
test al, al
jz .done
stosb
jmp .copy_name
.done:
mov byte [edi], 0
mov esi, output_path
mov edi, chunk_buffer
.create_dirs:
lodsb
stosb
test al, al
jz .dirs_done
cmp al, '/'
jne .create_dirs
mov byte [edi-1], 0
push eax
push 0
push chunk_buffer
call _CreateDirectoryA@8
pop eax
mov byte [edi-1], '/'
jmp .create_dirs
.dirs_done:
mov esp, ebp
pop ebp
ret
extract_d2_file:
push ebp
mov ebp, esp
push 0
push bytes_written
push msg_extract_len
push msg_extract
push dword [stdout_handle]
call _WriteFile@20
mov esi, output_path
call string_length
push 0
push bytes_written
push eax
push output_path
push dword [stdout_handle]
call _WriteFile@20
push 0
push bytes_written
push msg_newline_len
push msg_newline
push dword [stdout_handle]
call _WriteFile@20
push 0
push FILE_ATTRIBUTE_NORMAL
push CREATE_ALWAYS
push 0
push 0
push GENERIC_WRITE
push output_path
call _CreateFileA@28
cmp eax, INVALID_HANDLE_VALUE
je .error
mov ebx, eax
mov ecx, [d2_file_size]
.copy_loop:
mov eax, CHUNK_SIZE
cmp ecx, eax
jb .last_chunk
jmp .do_copy
.last_chunk:
mov eax, ecx
.do_copy:
push ecx
push 0
push bytes_read
push eax
push chunk_buffer
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .read_error
push 0
push bytes_written
push dword [bytes_read]
push chunk_buffer
push ebx
call _WriteFile@20
test eax, eax
jz .write_error
pop ecx
sub ecx, [bytes_read]
jnz .copy_loop
push ebx
call _CloseHandle@4
mov eax, 1
jmp .done
.read_error:
.write_error:
pop ecx
.error:
test ebx, ebx
jz .done
push ebx
call _CloseHandle@4
xor eax, eax
.done:
mov esp, ebp
pop ebp
ret
+240
View File
@@ -0,0 +1,240 @@
section .data
mar_entry_end db 0xFF
section .bss
mar_entry_type resb 1
mar_filename resb 260
mar_file_size resd 1
section .text
extract_mar:
push ebp
mov ebp, esp
push FILE_CURRENT
push 0
push 0
push dword [file_handle]
call _SetFilePointer@16
.process_entry:
push 0
push bytes_read
push 1
push mar_entry_type
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
mov al, [mar_entry_type]
cmp al, [mar_entry_end]
je .done
mov edi, mar_filename
.read_filename:
push 0
push bytes_read
push 1
push edi
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
mov al, [edi]
test al, al
jz .filename_done
inc edi
jmp .read_filename
.filename_done:
mov al, [mar_entry_type]
cmp al, 1
jne .process_entry
push 0
push bytes_read
push 4
push mar_file_size
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
call create_mar_path
call extract_mar_file
jmp .process_entry
.done:
mov esp, ebp
pop ebp
jmp cleanup
create_mar_path:
push ebp
mov ebp, esp
mov esi, input_file
mov edi, output_path
.copy_base:
lodsb
test al, al
jz .base_done
stosb
jmp .copy_base
.base_done:
dec edi
mov esi, extract_suffix
mov ecx, extract_suffix_len
rep movsb
mov byte [edi], '/'
inc edi
mov esi, mar_filename
.copy_name:
lodsb
test al, al
jz .name_done
cmp al, '\'
jne .store_char
mov al, '/'
.store_char:
stosb
jmp .copy_name
.name_done:
mov byte [edi], 0
mov esi, output_path
mov edi, chunk_buffer
.create_dirs:
lodsb
stosb
test al, al
jz .dirs_done
cmp al, '/'
jne .create_dirs
mov byte [edi-1], 0
push eax
push 0
push chunk_buffer
call _CreateDirectoryA@8
pop eax
mov byte [edi-1], '/'
jmp .create_dirs
.dirs_done:
mov esp, ebp
pop ebp
ret
extract_mar_file:
push ebp
mov ebp, esp
push 0
push bytes_written
push msg_extract_len
push msg_extract
push dword [stdout_handle]
call _WriteFile@20
mov esi, output_path
xor ecx, ecx
.count_len:
lodsb
test al, al
jz .print_path
inc ecx
jmp .count_len
.print_path:
push 0
push bytes_written
push ecx
push output_path
push dword [stdout_handle]
call _WriteFile@20
push 0
push bytes_written
push msg_newline_len
push msg_newline
push dword [stdout_handle]
call _WriteFile@20
push 0
push FILE_ATTRIBUTE_NORMAL
push CREATE_ALWAYS
push 0
push 0
push GENERIC_WRITE
push output_path
call _CreateFileA@28
cmp eax, INVALID_HANDLE_VALUE
je .error
mov ebx, eax
mov ecx, [mar_file_size]
.copy_loop:
mov eax, CHUNK_SIZE
cmp ecx, eax
jb .last_chunk
jmp .do_copy
.last_chunk:
mov eax, ecx
.do_copy:
push ecx
push 0
push bytes_read
push eax
push chunk_buffer
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .read_error
push 0
push bytes_written
push dword [bytes_read]
push chunk_buffer
push ebx
call _WriteFile@20
test eax, eax
jz .write_error
pop ecx
sub ecx, [bytes_read]
jnz .copy_loop
push ebx
call _CloseHandle@4
mov eax, 1
jmp .done
.read_error:
.write_error:
pop ecx
.error:
test ebx, ebx
jz .done
push ebx
call _CloseHandle@4
xor eax, eax
.done:
mov esp, ebp
pop ebp
ret
+264
View File
@@ -0,0 +1,264 @@
section .data
qar_filename_size equ 132
section .bss
qar_num_files resd 1
qar_file_size resd 1
qar_filename resb qar_filename_size
qar_padding resd 1
qar_header_pad resd 1
section .text
extract_qar:
push ebp
mov ebp, esp
push FILE_BEGIN
push 0
push 0
push dword [file_handle]
call _SetFilePointer@16
push FILE_CURRENT
push 0
push 4
push dword [file_handle]
call _SetFilePointer@16
push 0
push bytes_read
push 4
push qar_num_files
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
.extract_loop:
mov ecx, [qar_num_files]
test ecx, ecx
jz .done
push ecx
mov edi, qar_filename
mov ecx, qar_filename_size
xor al, al
rep stosb
pop ecx
push 0
push bytes_read
push qar_filename_size
push qar_filename
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
push 0
push bytes_read
push 4
push qar_padding
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
push 0
push bytes_read
push 4
push qar_file_size
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
push 0
push bytes_read
push 4
push qar_padding
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .done
mov al, [qar_filename]
test al, al
jz .next_file
call create_qar_path
call extract_qar_file
.next_file:
dec dword [qar_num_files]
jmp .extract_loop
.done:
mov esp, ebp
pop ebp
jmp cleanup
create_qar_path:
push ebp
mov ebp, esp
mov esi, input_file
mov edi, output_path
.copy_base:
lodsb
stosb
test al, al
jz .base_done
jmp .copy_base
.base_done:
dec edi
mov esi, extract_suffix
mov ecx, extract_suffix_len
rep movsb
mov byte [edi], '/'
inc edi
mov esi, qar_filename
.copy_name:
lodsb
test al, al
jz .name_done
cmp al, ' '
jz .name_done
cmp al, 0x0D
je .next_char
cmp al, 0x0A
je .next_char
cmp al, '\'
jne .store_char
mov al, '/'
.store_char:
stosb
.next_char:
jmp .copy_name
.name_done:
mov byte [edi], 0
mov esi, output_path
mov edi, chunk_buffer
.create_dirs:
lodsb
stosb
test al, al
jz .dirs_done
cmp al, '/'
jne .create_dirs
mov byte [edi-1], 0
push eax
push 0
push chunk_buffer
call _CreateDirectoryA@8
pop eax
mov byte [edi-1], '/'
jmp .create_dirs
.dirs_done:
mov esp, ebp
pop ebp
ret
extract_qar_file:
push ebp
mov ebp, esp
push 0
push bytes_written
push msg_extract_len
push msg_extract
push dword [stdout_handle]
call _WriteFile@20
mov esi, output_path
call string_length
push 0
push bytes_written
push eax
push output_path
push dword [stdout_handle]
call _WriteFile@20
push 0
push bytes_written
push msg_newline_len
push msg_newline
push dword [stdout_handle]
call _WriteFile@20
push 0
push FILE_ATTRIBUTE_NORMAL
push CREATE_ALWAYS
push 0
push 0
push GENERIC_WRITE
push output_path
call _CreateFileA@28
cmp eax, INVALID_HANDLE_VALUE
je .error
mov ebx, eax
mov ecx, [qar_file_size]
.copy_loop:
mov eax, CHUNK_SIZE
cmp ecx, eax
jb .last_chunk
jmp .do_copy
.last_chunk:
mov eax, ecx
.do_copy:
push ecx
push 0
push bytes_read
push eax
push chunk_buffer
push dword [file_handle]
call _ReadFile@20
test eax, eax
jz .read_error
push 0
push bytes_written
push dword [bytes_read]
push chunk_buffer
push ebx
call _WriteFile@20
test eax, eax
jz .write_error
pop ecx
sub ecx, [bytes_read]
jnz .copy_loop
push ebx
call _CloseHandle@4
mov eax, 1
jmp .done
.read_error:
.write_error:
pop ecx
.error:
test ebx, ebx
jz .done
push ebx
call _CloseHandle@4
xor eax, eax
.done:
mov esp, ebp
pop ebp
ret
+292
View File
@@ -0,0 +1,292 @@
extern _ExitProcess@4
extern _CreateFileA@28
extern _WriteFile@20
extern _ReadFile@20
extern _CloseHandle@4
extern _CreateDirectoryA@8
extern _GetStdHandle@4
extern _GetCommandLineA@0
extern _SetFilePointer@16
global start
section .data
CHUNK_SIZE equ 1048576
FILENAME_SIZE equ 256
STD_OUTPUT_HANDLE equ -11
GENERIC_READ equ 0x80000000
GENERIC_WRITE equ 0x40000000
FILE_SHARE_READ equ 0x00000001
CREATE_ALWAYS equ 2
OPEN_EXISTING equ 3
FILE_ATTRIBUTE_NORMAL equ 0x80
INVALID_HANDLE_VALUE equ -1
FILE_BEGIN equ 0
FILE_CURRENT equ 1
msg_usage db "Usage: unarchive <archive>", 13, 10
msg_usage_len equ $ - msg_usage
msg_invalid db "Invalid archive format", 13, 10
msg_invalid_len equ $ - msg_invalid
msg_invalid_bar db "Invalid BAR!", 13, 10
msg_invalid_bar_len equ $ - msg_invalid_bar
msg_open_error db "Failed to open file: ", 13, 10
msg_open_error_len equ $ - msg_open_error
msg_extract db "Extracting: "
msg_extract_len equ $ - msg_extract
msg_newline db 13, 10
msg_newline_len equ 2
mar_magic db "MASMAR0", 0
qar_magic db "QAR", 0
extract_suffix db "_extracted"
extract_suffix_len equ $ - extract_suffix
section .bss
align 16
input_file resb 260
output_path resb 1024
chunk_buffer resb CHUNK_SIZE
file_handle resd 1
stdout_handle resd 1
magic_buffer resb 8
bytes_read resd 1
bytes_written resd 1
format_type resb 1
extension resb 4
header_buffer resb 10
section .text
start:
push ebp
mov ebp, esp
push STD_OUTPUT_HANDLE
call _GetStdHandle@4
mov [stdout_handle], eax
call _GetCommandLineA@0
mov esi, eax
.skip_prog:
lodsb
test al, al
jz usage_error
cmp al, '"'
jne .not_quoted
.skip_quoted:
lodsb
test al, al
jz usage_error
cmp al, '"'
jne .skip_quoted
inc esi
jmp .find_arg
.not_quoted:
cmp al, ' '
je .find_arg
test al, al
jz usage_error
jmp .skip_prog
.find_arg:
lodsb
test al, al
jz usage_error
cmp al, ' '
je .find_arg
dec esi
mov edi, input_file
.copy_arg:
lodsb
test al, al
jz .arg_done
cmp al, ' '
je .arg_done
stosb
jmp .copy_arg
.arg_done:
mov byte [edi], 0
cmp byte [input_file], 0
je usage_error
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push 0
push FILE_SHARE_READ
push GENERIC_READ
push input_file
call _CreateFileA@28
cmp eax, INVALID_HANDLE_VALUE
je open_error
mov [file_handle], eax
push 0
push bytes_read
push 7
push magic_buffer
push dword [file_handle]
call _ReadFile@20
mov esi, magic_buffer
mov edi, mar_magic
mov ecx, 7
repe cmpsb
je detect_mar
push FILE_BEGIN
push 0
push 0
push dword [file_handle]
call _SetFilePointer@16
push 0
push bytes_read
push 3
push magic_buffer
push dword [file_handle]
call _ReadFile@20
mov esi, magic_buffer
mov edi, qar_magic
mov ecx, 3
repe cmpsb
je detect_qar
mov esi, input_file
call get_extension
test eax, eax
jz try_bar
mov esi, extension
mov al, 'd'
cmp byte [esi], al
jne try_bar
mov al, '2'
cmp byte [esi+1], al
je detect_d2
try_bar:
push FILE_BEGIN
push 0
push 0
push dword [file_handle]
call _SetFilePointer@16
mov byte [format_type], 3
jmp process_archive
detect_mar:
mov byte [format_type], 1
jmp process_archive
detect_qar:
mov byte [format_type], 2
jmp process_archive
detect_d2:
mov byte [format_type], 4
jmp process_archive
process_archive:
push FILE_BEGIN
push 0
push 0
push dword [file_handle]
call _SetFilePointer@16
movzx eax, byte [format_type]
cmp al, 1
je extract_mar
cmp al, 2
je extract_qar
cmp al, 3
je extract_bar
cmp al, 4
je extract_d2
jmp cleanup
string_length:
push ebp
mov ebp, esp
mov edi, esi
xor al, al
mov ecx, -1
repne scasb
mov eax, edi
sub eax, esi
dec eax
mov esp, ebp
pop ebp
ret
get_extension:
xor eax, eax
mov edi, extension
mov ebx, esi
.find_dot:
lodsb
test al, al
jz .not_found
cmp al, '.'
jne .find_dot
.copy_ext:
lodsb
test al, al
jz .done
stosb
jmp .copy_ext
.done:
mov eax, 1
ret
.not_found:
xor eax, eax
ret
cleanup:
push dword [file_handle]
call _CloseHandle@4
xor eax, eax
push eax
call _ExitProcess@4
usage_error:
push 0
push bytes_written
push msg_usage_len
push msg_usage
push dword [stdout_handle]
call _WriteFile@20
push 1
call _ExitProcess@4
open_error:
push 0
push bytes_written
push msg_open_error_len
push msg_open_error
push dword [stdout_handle]
call _WriteFile@20
mov esi, input_file
call string_length
push 0
push bytes_written
push eax
push input_file
push dword [stdout_handle]
call _WriteFile@20
push 1
call _ExitProcess@4
%include "mar.asm"
%include "qar.asm"
%include "bar.asm"
%include "dtwo.asm"