mirror of
https://github.com/Elpisdev/unarchive.git
synced 2026-09-27 09:23:06 +03:00
xd
xd
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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"
|
||||
Reference in New Issue
Block a user