📄 unopix.asm
字号:
; ----------------------------------------- ;
; Unopix 1.10 final ;
; Coded on FASM 1.66+ ;
; Copyright (c) 2005,2006 by bagie ;
; ----------------------------------------- ;
format PE Console 4.0
entry EntryPoint
Version equ '1.10'
BuildDate equ 'Final [15.09.2006]'
include '%fasminc%/win32ax.inc'
section '.unopix' code data readable writeable executable
proc EntryPoint
stdcall InitConsole,_AppTtle
stdcall Writeln,_AppLogo
stdcall GetMainArgs
.if [_argc]
stdcall Randomize
stdcall GetParams
stdcall ProtectFile,eax,edx
push eax
.else
stdcall Writeln,_Usage
push ERROR_INVALID_PARAMETER
.endif
call [ExitProcess]
endp
include 'console.inc'
include 'sysutils.inc'
include 'windows.inc'
;include 'morph.inc'
include 'fcrypt.inc'
PROTECTION_FLAG_MAKEBACKUP = $00000001
PROTECTION_FLAG_SAVEOVERLAY = $00000002
PROTECTION_FLAG_ANTIDUMP_MODE = $00000004
proc GetParams ; -> EAX: pointer to filename | -> EDX: flags for ProtectFile func
push ebx edi esi
xor edi,edi
mov esi,[_argc]
.while esi > 1
stdcall ParamStr,esi
mov ebx,eax
invoke lstrlenA,ebx
invoke CharUpperBuffA,ebx,eax
;=====================================;
call @f
db '-B',0
@@:
invoke lstrcmpA,ebx,
.if eax = 0
mov eax,edi
and eax,PROTECTION_FLAG_MAKEBACKUP
.if eax = 0
add edi,PROTECTION_FLAG_MAKEBACKUP
.endif
jmp @_next_param
.endif
;=====================================;
call @f
db '-E',0
@@:
invoke lstrcmpA,ebx,
.if eax = 0
mov eax,edi
and eax,PROTECTION_FLAG_SAVEOVERLAY
.if eax = 0
add edi,PROTECTION_FLAG_SAVEOVERLAY
.endif
jmp @_next_param
.endif
;=====================================;
call @f
db '-D',0
@@:
invoke lstrcmpA,ebx,
.if eax = 0
mov eax,edi
and eax,PROTECTION_FLAG_ANTIDUMP_MODE
.if eax = 0
add edi,PROTECTION_FLAG_ANTIDUMP_MODE
.endif
jmp @_next_param
.endif
;=====================================;
@_next_param:
dec esi
.endw
stdcall ParamStr,1
mov edx,edi
pop esi edi ebx
ret
endp
proc ProtectFile,lpFileName:LPCTSTR,dwFlags:DWORD
locals
xyCoord dd ?
hFile dd ?
hMap dd ?
ptrMap dd ?
lpBuff db 256 dup (?)
dwFileSize dd 0
dwExtraSize dd 0
dwIsDllFile dd 0
dwOriginalEP dd ?
dwLoaderRVA dd ?
dwOepAddress dd ?
dwImportAddr dd ?
dwAdler32Val dd ?
endl
;------------------------------------
push ebx edi esi
lea ebx,[lpBuff]
invoke GetFullPathNameA,[lpFileName],256,ebx,Dummy
invoke CreateFileA,ebx,GENERIC_READ+GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
mov [hFile],eax
.if eax <> INVALID_HANDLE_VALUE
cinvoke wsprintfA,ebx,_Filename,[lpFileName]
stdcall Writeln,ebx
.else
invoke GetLastError
push eax
push eax ; return code
.if eax = ERROR_FILE_NOT_FOUND
cinvoke wsprintfA,ebx,_FileNotFound,[lpFileName]
stdcall ShowError,ebx,
jmp @err
.else
cinvoke wsprintfA,ebx,_ErrorOpenFile,[lpFileName]
stdcall ShowError,ebx,
jmp @err
.endif
.endif
mov eax,[dwFlags]
and eax,PROTECTION_FLAG_MAKEBACKUP
.if eax
invoke lstrcpyA,ebx,[lpFileName]
call @f
db '.bak',0
@@:
invoke lstrcatA,ebx,
invoke SetFileAttributesA,[lpFileName],0
invoke CopyFileA,[lpFileName],ebx,FALSE
.endif
invoke GetFileSize,[hFile],0
.if eax < 512
push ERROR_INVALID_DATA ; return code
stdcall ShowError,_ErrorNotValid,ERROR_INVALID_DATA
jmp @err
.endif
mov [dwFileSize],eax
add eax,loader_size
invoke CreateFileMappingA,[hFile],0,PAGE_READWRITE,0,eax,0
mov [hMap],eax
invoke GetLastError
.if eax <> ERROR_SUCCESS
push eax ; return code
stdcall ShowError,_ErrorMapFile,eax
jmp @err
.endif
invoke MapViewOfFile,[hMap],FILE_MAP_ALL_ACCESS,0,0,0
mov [ptrMap],eax
mov edi,eax
invoke GetLastError
.if eax <> ERROR_SUCCESS
push eax ; return code
stdcall ShowError,_ErrorMapFile,eax
jmp @err
.endif
.if word [edi+IMAGE_DOS_HEADER.e_magic] <> IMAGE_DOS_SIGNATURE
push ERROR_INVALID_EXE_SIGNATURE ; return code
stdcall ShowError,_ErrorNotValid,ERROR_INVALID_EXE_SIGNATURE
jmp @err
.endif
.if word [edi+IMAGE_DOS_HEADER.e_lfarlc] < 40h
push ERROR_BAD_EXE_FORMAT ; return code
stdcall ShowError,_ErrorNotValid,ERROR_BAD_EXE_FORMAT
jmp @err
.endif
mov esi,[edi+IMAGE_DOS_HEADER._lfanew]
.if esi < SizeOfDosStub
push ERROR_BAD_EXE_FORMAT ; return code
stdcall ShowError,_ErrorBadEntry,ERROR_BAD_EXE_FORMAT
jmp @err
.endif
add esi,edi
invoke IsBadReadPtr,esi,4
.if eax <> 0
push ERROR_NOACCESS ; return code
stdcall ShowError,_ErrorNotValid,ERROR_NOACCESS
jmp @err
.endif
.if dword [esi+IMAGE_NT_HEADERS.Signature] <> IMAGE_NT_SIGNATURE
push ERROR_BAD_EXE_FORMAT ; return code
stdcall ShowError,_ErrorNotValid,ERROR_BAD_EXE_FORMAT
jmp @err
.endif
mov eax,esi
sub eax,edi
.if eax < sizeof.IMAGE_DOS_HEADER
push ERROR_BAD_EXE_FORMAT ; return code
stdcall ShowError,_ErrorBadEntry,ERROR_BAD_EXE_FORMAT
jmp @err
.endif
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint] < $1000
push ERROR_BAD_EXE_FORMAT ; return code
stdcall ShowError,_ErrorBadEntry,ERROR_BAD_EXE_FORMAT
jmp @err
.endif
call WhereXY
mov [xyCoord],eax
call @f
db 'Processing...',0
@@:
stdcall Write,
invoke Sleep,500
;===========================================
; writing new DOS stub
push [edi+IMAGE_DOS_HEADER._lfanew]
invoke RtlMoveMemory,edi,DosStub,SizeOfDosStub
pop [edi+IMAGE_DOS_HEADER._lfanew]
lea eax,[edi+SizeOfDosStub]
mov ecx,[edi+IMAGE_DOS_HEADER._lfanew]
sub ecx,SizeOfDosStub
invoke RtlZeroMemory,eax,ecx
xor eax,eax ; fix some values
mov [esi+IMAGE_NT_HEADERS.FileHeader.Machine],IMAGE_FILE_MACHINE_I386
mov [esi+IMAGE_NT_HEADERS.FileHeader.TimeDateStamp],eax
mov [esi+IMAGE_NT_HEADERS.FileHeader.PointerToSymbolTable],eax
mov [esi+IMAGE_NT_HEADERS.FileHeader.NumberOfSymbols],eax
mov [esi+IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader],IMAGE_SIZEOF_NT_OPTIONAL_HEADER
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.Magic],IMAGE_NT_OPTIONAL_HDR_MAGIC
mov word [esi+IMAGE_NT_HEADERS.OptionalHeader.MajorLinkerVersion],ax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.SizeOfCode],eax ; ?
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.SizeOfInitializedData],eax ; ?
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.SizeOfUninitializedData],eax ; ?
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.BaseOfCode],eax ; ?
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.BaseOfData],eax ; ?
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.SectionAlignment],$1000 ; SectionAlignment
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.FileAlignment],$200 ; FileAlignment
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.MajorOperatingSystemVersion],1
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.MinorOperatingSystemVersion],ax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.MajorImageVersion],ax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.MinorImageVersion],ax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.MajorSubsystemVersion],4
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.MinorSubsystemVersion],ax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.Win32VersionValue],eax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.CheckSum],eax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.NumberOfRvaAndSizes],$10
; clear bound import & debug directory
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryBoundImport.VirtualAddress],eax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryBoundImport.Size],eax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryDebug.VirtualAddress],eax
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryDebug.Size],eax
; save reloc RVA
mov edx,[esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryBaseReloc.VirtualAddress]
mov [loader_reloc_rva],edx
mov edx,[esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryBaseReloc.Size]
mov [loader_reloc_size],edx
mov edx,[esi+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
mov [loader_reloc_base],edx
movzx eax,[esi+IMAGE_NT_HEADERS.FileHeader.Characteristics]
mov [loader_dllflag],eax ; set loader dll flag
mov [loader_dllflag_2],eax ; set loader dll flag
and eax,IMAGE_FILE_DLL
mov [dwIsDllFile],eax
mov eax,IMAGE_SIZEOF_SECTION_HEADER
movzx ecx,[esi+IMAGE_NT_HEADERS.FileHeader.NumberOfSections] ; number of sections
dec cx
mul cx
lea eax,[esi+4+IMAGE_SIZEOF_FILE_HEADER+IMAGE_SIZEOF_NT_OPTIONAL_HEADER+eax] ; pointer to last section
mov edx,[eax+IMAGE_SECTION_HEADER.PointerToRawData]
add edx,[eax+IMAGE_SECTION_HEADER.SizeOfRawData]
mov ecx,[dwFileSize]
sub ecx,edx
mov [dwExtraSize],ecx ; overlay size
mov ecx,[eax+IMAGE_SECTION_HEADER.VirtualAddress]
add ecx,[eax+IMAGE_SECTION_HEADER.SizeOfRawData]
mov [dwLoaderRVA],ecx ; loader RVA
mov edx,[eax+IMAGE_SECTION_HEADER.SizeOfRawData]
add edx,loader_size ; increment raw size of lasts section
mov [eax+IMAGE_SECTION_HEADER.SizeOfRawData],edx
; align edx(lastsection.VirtualSize) value
xor ecx,ecx
ror edx,12
test edx,$FF000000
je @f
mov ecx,$1000
@@: and edx,$00FFFFFF
shl edx,12
add edx,ecx
mov [eax+IMAGE_SECTION_HEADER.VirtualSize],edx
mov edx,[eax+IMAGE_SECTION_HEADER.VirtualAddress]
add edx,[eax+IMAGE_SECTION_HEADER.VirtualSize]
; align edx(SizeOfImage) value
xor ecx,ecx
ror edx,12
test edx,$FF000000
je @f
mov ecx,$1000
@@: and edx,$00FFFFFF
shl edx,12
add edx,ecx
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage],edx
add eax,IMAGE_SIZEOF_SECTION_HEADER ; address of the end of headers
push eax
mov eax,[esi+IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint]
add eax,[esi+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
mov [dwOriginalEP],eax
.if [dwIsDllFile] <> 0
mov eax,[esi+IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint]
mov edx,eax
and eax,$FFFF0000
and edx,$0000FFFF
mov [loader_oep_dll_part1],eax ; save OEP
mov [loader_oep_dll_part2],edx
.else
mov edx,eax
and eax,$FFFF0000
and edx,$0000FFFF
mov [loader_oep_part1],eax ; save OEP
mov [loader_oep_part2],edx
.endif
lea eax,[esi+IMAGE_NT_HEADERS.OptionalHeader.SizeOfCode] ; far jump (maximum 12 bytes) location
sub eax,edi
mov [esi+IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint],eax ; set new EntryPoint
; copy "jump to main code"
lea eax,[edi+eax]
mov edx,[dwLoaderRVA]
.if [dwIsDllFile] <> 0
; DLL far jump
mov [far_jump_dll_address],edx
invoke RtlMoveMemory,eax,far_jump_dll,far_jump_dll_size
.else
add edx,[esi+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
mov [far_jump_address],edx
invoke RtlMoveMemory,eax,far_jump,far_jump_size
.endif
lea ebx,[esi+4+IMAGE_SIZEOF_FILE_HEADER+IMAGE_SIZEOF_NT_OPTIONAL_HEADER] ; pointer to first section
pop eax ; address of the end of headers
mov ecx,[ebx+IMAGE_SECTION_HEADER.PointerToRawData]
add ecx,edi
sub ecx,eax
invoke RtlZeroMemory,eax,ecx ; fill end of headers with zeros
pushad
; generate loader rubbish code
invoke GenerateRubbishCode,loader_rubbish_0_137,137,0
invoke GenerateRubbishCode,loader_rubbish_1_137,137,0
invoke GenerateRubbishCode,loader_rubbish_2_137,137,0
invoke GenerateRubbishCode,loader_rubbish_3_137,137,0
invoke GenerateRubbishCode,loader_rubbish_4_137,137,0
invoke GenerateRubbishCode,loader_rubbish_5_67,67,0
invoke GenerateRubbishCode,loader_rubbish_6_111,111,0
invoke GenerateRubbishCode,loader_rubbish_7_507,507,0
invoke GenerateRubbishCode,loader_rubbish_8_501,501,0
invoke GenerateRubbishCode,loader_rubbish_9_69,69,0
invoke GenerateRubbishCode,loader_rubbish_10_121,121,0
invoke GenerateRubbishCode,loader_rubbish_11_119,119,0
invoke GenerateRubbishCode,loader_rubbish_12_37,37,0
invoke GenerateRubbishCode,loader_rubbish_13_91,91,0
invoke GenerateRubbishCode,loader_rubbish_21_77,77,0
invoke GenerateRubbishCode,loader_rubbish_22_33,33,0
invoke GenerateRubbishCode,loader_rubbish_23_117,117,0
invoke GenerateRubbishCode,loader_rubbish_24_233,233,0
invoke GenerateRubbishCode,loader_rubbish_25_47,47,0
invoke GenerateRubbishCode,loader_rubbish_26_57,57,0
invoke GenerateRubbishCode,loader_rubbish_27_137,137,0
invoke GenerateRubbishCode,loader_rubbish_28_149,149,0
invoke GenerateRubbishCode,loader_rubbish_29_117,117,0
invoke GenerateRubbishCode,loader_rubbish_30_233,233,0
invoke GenerateRubbishCode,loader_rubbish_31_113,113,0
invoke GenerateRubbishCode,loader_rubbish_32_43,43,0
invoke GenerateRubbishCode,loader_rubbish_33_99,99,0
invoke GenerateRubbishCode,loader_rubbish_34_551,551,0
invoke GenerateRubbishCode,loader_rubbish_oep1_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep2_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep3_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep4_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep5_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep6_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep7_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep8_33,33,0
invoke GenerateRubbishCode,loader_rubbish_oep9_33,33,0
; exe loader
mov ebx,[dwLoaderRVA]
add ebx,[esi+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
lea eax,[ebx+loader_rubbish_14_133-loader_proc]
invoke GenerateRubbishCode,loader_rubbish_14_133,133,eax
lea eax,[ebx+loader_rubbish_15_57-loader_proc]
invoke GenerateRubbishCode,loader_rubbish_15_57,57,eax
lea eax,[ebx+loader_rubbish_16_87-loader_proc]
invoke GenerateRubbishCode,loader_rubbish_16_87,87,eax
lea eax,[ebx+loader_rubbish_17_63-loader_proc]
invoke GenerateRubbishCode,loader_rubbish_17_63,63,eax
lea eax,[ebx+loader_rubbish_18_531-loader_proc]
invoke GenerateRubbishCode,loader_rubbish_18_531,531,eax
lea eax,[ebx+loader_rubbish_19_263-loader_proc]
invoke GenerateRubbishCode,loader_rubbish_19_263,263,eax
lea eax,[ebx+loader_rubbish_20_127-loader_proc]
invoke GenerateRubbishCode,loader_rubbish_20_127,127,eax
mov eax,[dwFlags]
and eax,PROTECTION_FLAG_ANTIDUMP_MODE
.if eax = 0
lea eax,[ebx+loader_antidump_start-loader_proc]
invoke GenerateRubbishCode,loader_antidump_start,loader_antidump_end-loader_antidump_start,eax
.endif
popad
movzx ecx,[esi+IMAGE_NT_HEADERS.FileHeader.NumberOfSections] ; number of sections
mov byte [lpBuff],0
@_loop:
push ecx
; set readable+writeable attributes
or [ebx+IMAGE_SECTION_HEADER.Characteristics],IMAGE_SCN_MEM_READ+IMAGE_SCN_MEM_WRITE
and [ebx+IMAGE_SECTION_HEADER.Characteristics],not IMAGE_SCN_MEM_SHARED
.if [ebx+IMAGE_SECTION_HEADER.SizeOfRawData] = 0 ; this section can contain uninitialized data (.bss ???)
.if byte [lpBuff] = 0
mov byte [lpBuff],$FF
invoke RtlMoveMemory,ebx,SECTION_NAME_DATA,IMAGE_SIZEOF_SHORT_NAME ; set name '.data'
.else
invoke RtlZeroMemory,ebx,IMAGE_SIZEOF_SHORT_NAME ; clear name
;invoke RtlMoveMemory,ebx,SECTION_NAME_DATA,IMAGE_SIZEOF_SHORT_NAME ; set name '.data'
.endif
.else
invoke RtlZeroMemory,ebx,IMAGE_SIZEOF_SHORT_NAME ; clear name
;invoke RtlMoveMemory,ebx,SECTION_NAME_DATA,IMAGE_SIZEOF_SHORT_NAME ; set name '.data'
mov edx,[ebx+IMAGE_SECTION_HEADER.VirtualAddress]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryBaseReloc.VirtualAddress] >= edx
add edx,[ebx+IMAGE_SECTION_HEADER.VirtualSize]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryBaseReloc.VirtualAddress] < edx
invoke RtlMoveMemory,ebx,SECTION_NAME_RELOC,IMAGE_SIZEOF_SHORT_NAME ; set name '.reloc'
.endif
.endif
mov edx,[ebx+IMAGE_SECTION_HEADER.VirtualAddress]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryTls.VirtualAddress] >= edx
add edx,[ebx+IMAGE_SECTION_HEADER.VirtualSize]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryTls.VirtualAddress] < edx
invoke RtlMoveMemory,ebx,SECTION_NAME_RDATA,IMAGE_SIZEOF_SHORT_NAME ; set name '.rdata'
.endif
.endif
mov edx,[ebx+IMAGE_SECTION_HEADER.VirtualAddress]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryExport.VirtualAddress] >= edx
add edx,[ebx+IMAGE_SECTION_HEADER.VirtualSize]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryExport.VirtualAddress] < edx
invoke RtlMoveMemory,ebx,SECTION_NAME_EDATA,IMAGE_SIZEOF_SHORT_NAME ; set name '.edata'
; fix export
mov eax,[esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryExport.VirtualAddress]
sub eax,[ebx+IMAGE_SECTION_HEADER.VirtualAddress]
add eax,[ebx+IMAGE_SECTION_HEADER.PointerToRawData]
add eax,edi
mov [eax+IMAGE_EXPORT_DIRECTORY.TimeDateStamp],0
.endif
.endif
mov edx,[ebx+IMAGE_SECTION_HEADER.VirtualAddress]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryImport.VirtualAddress] >= edx
add edx,[ebx+IMAGE_SECTION_HEADER.VirtualSize]
.if [esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryImport.VirtualAddress] < edx
invoke RtlMoveMemory,ebx,SECTION_NAME_IDATA,IMAGE_SIZEOF_SHORT_NAME ; set name '.idata'
; fix import
mov eax,[esi+IMAGE_NT_HEADERS.OptionalHeader.DataDirectoryImport.VirtualAddress]
sub eax,[ebx+IMAGE_SECTION_HEADER.VirtualAddress]
add eax,[ebx+IMAGE_SECTION_HEADER.PointerToRawData]
add eax,edi
mov [dwImportAddr],eax ; mem addr of import table
; ---
.while [eax+IMAGE_IMPORT_DIRECTORY_ENTRY.NameRVA] <> 0
xor edx,edx
mov [eax+IMAGE_IMPORT_DIRECTORY_ENTRY.TimeDateStamp],edx
push eax
mov eax,[eax+IMAGE_IMPORT_DIRECTORY_ENTRY.NameRVA]
push eax
stdcall ImageRvaToSection,esi,edi,eax
or eax,eax
jne @f
add esp,4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -