So sánh cách biên dịch VB6 ra pcode và native code.

NhanSu

SMod
Thành viên BQT
Chào các bạn. Chủ đề này mình sẽ trình bày về 2 cách biên dịch Project VB6 ra Pcode và Native code.
Bài 1 Cách biên dịch:
- Code ví dụ:
Tạo project Standard exe, tại cửa sổ Project explorer (góc trên phải màn hình, có chữ Project1) bấm chuột phải vào biểu tượng Form1 chọn Remove để xóa sau đó bấm chuột phải vào Project1, chọn Add - Module để thêm Module1.
Nhập code vào module:
Mã:
Sub Main()
    Dim s As String
    s = InputBox("Enter password:")
    If CheckPass(s) Then
        MsgBox "Correct password"
    Else
        MsgBox "Wrong password"
    End If
End Sub
Function CheckPass(ByVal s As String) As Boolean
    s = s & "xyz"
    If s = "abcxyz" Then
        CheckPass = True
    Else
        CheckPass = False
    End If
End Function
Code làm nhiệm vụ rất đơn giản: hàm Main nhập password bằng Inputbox rồi gọi hàm ChecPass; hàm CheckPass sẽ thực hiện phép biến đổi rồi so sánh với chuỗi gốc, trả kết quả dạng Boolean về Main; hàm Main đưa ra thông báo pass đúng hay sai

Bạn cần đăng nhập để thấy đính kèm


Bạn cần đăng nhập để thấy đính kèm


- Để chọn cách biên dịch, ta bấm chuột phải vào Project1 ở cửa sổ Project explorer, chọn Project1 properties. Chọn tab Compile:

Bạn cần đăng nhập để thấy đính kèm

Trong tab Compile sẽ có lựa chọn Compile to pcode và Compile to Native code. Nếu chọn native code thì có thêm một số lựa chọn: Optimize for fast code (tối ưu code về tốc độ), Optimize for small code (tối ưu kích thước file tạo ra), Favor pentium pro (dùng cho CPU pentium pro, CPU này đã cũ), Create Symbolic debug info (tạo thông tin phục vụ debug), No optimization (không tối ưu).
Sau khi chọn kiểu compile, vào menu file, chọn make Project1.exe. Ở đây mình tạo 2 file Project1_native.exe và Project1_pcode.exe để tiện việc so sánh trong bài sau.
 
  • Like
Reactions: CRV

NhanSu

SMod
Thành viên BQT
Bài 2: So sánh hai kiểu biên dịch. Có nhiều bài trên internet về so sánh, ví dụ tại link sau

Mình tạm dịch bài 2 như sau:
"Native code là kiểu biên dịch ra mã máy, tối ưu cho tốc độ nhưng tạo ra file exe lớn hơn.
Pcode là mã giả, là mã trung gian giữa mã nguồn VB và mã máy. Khi chạy, VB thông dịch pcode rẫm máy. Bằng cách biên dịch trực tiếp ra mã máy (native code), ta bỏ qua được bước trung gian. Pcode nhỏ hơn nhưng chậm hơn native code.
Chú ý VB project native hay pcode vẫn cần VB runtime DLL (MSVBVM60.DLL).
 

NhanSu

SMod
Thành viên BQT
Bài 3: So sánh 2 kiểu biên dịch ở góc độ bảo mật: bài này, mình minh họa cách dùng VB decompiler dịch ngược 2 file. Tải vbdecompiler tại địa chỉ

Sau khi cài đặt và chạy, chương trình hiện lên như sau (mình sử dụng bản Pro do @OnceMore cung cấp):
Bạn cần đăng nhập để thấy đính kèm


Vào menu File, chọn Open program, chọn file Project1_pcode.exe: VB decompiler sẽ nạp file và dịch ngược ra VB, bấm và 2 thủ tục Proc... ở bên trái ta sẽ được code dịch ngược:
Sub main:
Mã:
Public Sub Proc_0_0_40163C
  'Data Table: 4010C8
  loc_4015C9: var_A8 = "": var_C8 = "": var_E8 = "": var_108 = "": var_128 = "": var_148 = "" 'Ignore this
  loc_4015E2: If Proc_0_1_401570(InputBox("Enter password:", var_C8, var_E8, var_108, var_128, var_148, var_168)) Then
  loc_4015FE:   MsgBox("Correct password", 0, var_C8, var_E8, var_108)
  loc_401603:   var_A8 = "": var_C8 = "": var_E8 = "" 'Ignore this
  loc_401611: Else
  loc_40162A:   MsgBox("Wrong password", 0, var_C8, var_E8, var_108)
  loc_40162F:   var_A8 = "":   var_C8 = "":   var_E8 = "" 'Ignore this
  loc_40163A: End If
  loc_40163A: Exit Sub
  loc_40163B: IDE.GoTo loc_4016CB 'Ignore this
End Sub
Mã:
Public Sub Proc_0_1_401570(arg_C) '401570
  'Data Table: 4010C8
  Dim var_86 As Integer
  loc_401547: var_8C = arg_C
  loc_40155C: If (var_8C & "xyz" = "abcxyz") Then
  loc_401561:   var_86 = &HFF
  loc_401567: Else
  loc_401569:   var_86 = 0
  loc_40156C: End If
  loc_40156C: Result var_86 End Sub 'Integer
  loc_40156E: If CBool(var_86) Then
  loc_40156E: End If
End Sub

Bạn cần đăng nhập để thấy đính kèm


Đọc code trên, ta thấy code được dịch ra VB nhưng tên bị thay đổi và các lệnh không giống mã nguồn ở bài 1. Tuy vậy cũng có thể đoán được logic của chuơng trình.
 

NhanSu

SMod
Thành viên BQT
Bài 4: Dùng VB decompiler mở file Project1_native.exe để so sánh, ta được code:
Mã:
Public Sub Proc_0_0_4016D0
  loc_00401744: var_8C = "Enter password:"
  loc_00401758: var_24 = "Enter password:"
  loc_00401784: var_14 = InputBox(var_24, var_34, var_44, var_54, var_64, var_74, var_84)
  loc_004017AB: call undef 'Ignore this '__vbaFreeVarList(00000007, var_24, var_34, var_44, var_54, var_64, var_74, var_84, 80020004h, 0000000Ah, %ecx = %S_edx_S)
  loc_004017B8: var_eax = Proc_0_1_4018C0(var_14)
  loc_004017D2: If Proc_0_1_4018C0(var_14) Then
  loc_004017DD:   var_8C = "Correct password"
  loc_00401805:   MsgBox("Correct password", 0, var_34, var_44, var_54)
  loc_0040181B:   GoTo loc_00401864
  loc_0040181D: End If
  loc_00401826: var_8C = "Wrong password"
  loc_0040183A: var_24 = "Wrong password"
  loc_0040184E: MsgBox(var_24, 0, var_34, var_44, var_54)
  loc_00401864: 'Referenced from: 0040181B
  loc_00401866: call undef 'Ignore this '__vbaFreeVarList(00000004, var_24, var_34, var_44, var_54, var_24, var_34, var_44, var_54)
  loc_00401874: GoTo loc_004018A1
  loc_00401897: call undef 'Ignore this '__vbaFreeVarList(00000007, var_24, var_34, var_44, var_54, var_64, var_74, var_84, global_004018AB)
  loc_004018A0: Exit Sub
  loc_004018A1: 'Referenced from: 00401874
End Sub
Mã:
Public Sub Proc_0_1_4018C0
  loc_004018F6: var_18 = arg_8
  loc_00401910: var_18 = var_18 & "xyz"
  loc_00401930: eax = (var_18 = "abcxyz") - 1
  loc_00401931: var_14 = (var_18 = "abcxyz") - 1
End Sub
Ta thấy code đã được dịch nửa hợp ngữ (eax là ký hiệu thanh ghi của CPU), nửa VB và không đầy đủ. Chuyển sang tab Disassembler ta được code đầy đủ dạng hợp ngữ, dưới đây là code của function CheckPass:
Mã:
 loc_004018C0: push ebp
  loc_004018C1: mov ebp, esp
  loc_004018C3: sub esp, 00000008h
  loc_004018C6: push 004010B6h ; undef 'Ignore this
  loc_004018CB: mov eax, fs:[00000000h]
  loc_004018D1: push eax
  loc_004018D2: mov fs:[00000000h], esp
  loc_004018D9: sub esp, 0000000Ch
  loc_004018DC: push ebx
  loc_004018DD: push esi
  loc_004018DE: push edi
  loc_004018DF: mov var_8, esp
  loc_004018E2: mov var_4, 004010A0h
  loc_004018E9: mov edx, arg_8
  loc_004018EC: lea ecx, var_18
  loc_004018EF: mov var_18, 00000000h
  loc_004018F6: call [0040105Ch] ; %ecx = %S_edx_S '__vbaStrCopy
  loc_004018FC: mov eax, var_18
  loc_004018FF: push eax
  loc_00401900: push 004013C0h ; "xyz"
  loc_00401905: call [00401014h] ; @%StkVar2 & %x1 '__vbaStrCat
  loc_0040190B: mov edx, eax
  loc_0040190D: lea ecx, var_18
  loc_00401910: call [00401074h] ; %ecx = %S_edx_S '__vbaStrMove
  loc_00401916: mov ecx, var_18
  loc_00401919: push ecx
  loc_0040191A: push 004013CCh ; "abcxyz"
  loc_0040191F: call [00401034h] ; @(%StkVar2 = %x1) '__vbaStrCmp
  loc_00401925: neg eax
  loc_00401927: sbb eax, eax
  loc_00401929: push 0040193Eh
  loc_0040192E: neg eax
  loc_00401930: dec eax
  loc_00401931: mov var_14, eax
  loc_00401934: lea ecx, var_18
  loc_00401937: call [00401084h] ; %ecx = "" '__vbaFreeStr
  loc_0040193D: ret
  loc_0040193E: mov ecx, var_10
  loc_00401941: mov ax, var_14
  loc_00401945: pop edi
  loc_00401946: pop esi
  loc_00401947: mov fs:[00000000h], ecx
  loc_0040194E: pop ebx
  loc_0040194F: mov esp, ebp
  loc_00401951: pop ebp
  loc_00401952: retn 0004h
Ta thấy code rất khó hiểu mặc dù mã nguồn VB thì ngắn.
Kết luận 4 bài trên, ta nên biên dịch file dạng native code (DLL cũng tuơng tự) ra dạng native để tăng tốc độ thực thi và tăng bảo mật.
 
B

bvtvba

Guest
Cảm ơn bài chia sẻ của bác.
Theo em biết, VB6 mặc định nó ở chế độ N code. Những ai cài VB6 có thể kiểm chứng.
Bạn cần đăng nhập để thấy hình ảnh


Bạn cần đăng nhập để thấy hình ảnh


Em không có bản pro, xài bản vớ vẩn thôi.
Bạn cần đăng nhập để thấy hình ảnh

Theo em thấy thì tên hàm và tên thủ tục có thể suy đoán. Với người có khả năng code, điều này cũng đã giúp họ tự code lại một chương trình nếu không quá phức tạp.
Nên mã hóa tên hàm thì tốt. Việc mã hóa có thể gây khó khăn cho chính người code. Nên bước quản lý tên hàm có lẽ cần một topic riêng để bàn sâu hơn.
 

NhanSu

SMod
Thành viên BQT
Bài này mình sẽ tách hàm CheckPass vào DLL như sau:
Tạo Project ActiveX DLL, thêm code vào class1:
Mã:
Function CheckPass(ByVal s As String) As Boolean
    s = s & "xyz"
    If s = "abcxyz" Then
        CheckPass = True
    Else
        CheckPass = False
    End If
End Function
Biên dịch ra DLL (native code, đây là lựa chọn mặc định). Load DLL bằng VB decompiler, ta được:

Bạn cần đăng nhập để thấy đính kèm


Mã:
Public Function CheckPass(s) '110018E0
  Dim arg_8 As Me
  loc_11001914: arg_8.AddRef 'Ignore this
  loc_11001923: var_1C = s
  loc_1100193D: var_1C = var_1C & "xyz"
  loc_11001958: eax = (var_1C = "abcxyz") - 1
  loc_11001959: var_18 = (var_1C = "abcxyz") - 1
End Function
Tab disassebler:
Mã:
loc_110018E0: push ebp
  loc_110018E1: mov ebp, esp
  loc_110018E3: sub esp, 0000000Ch
  loc_110018E6: push 110010B6h ; undef 'Ignore this
  loc_110018EB: mov eax, fs:[00000000h]
  loc_110018F1: push eax
  loc_110018F2: mov fs:[00000000h], esp
  loc_110018F9: sub esp, 00000010h
  loc_110018FC: push ebx
  loc_110018FD: push esi
  loc_110018FE: push edi
  loc_110018FF: mov var_C, esp
  loc_11001902: mov var_8, 11001098h
  loc_11001909: xor esi, esi
  loc_1100190B: mov var_4, esi
  loc_1100190E: mov eax, arg_8
  loc_11001911: push eax
  loc_11001912: mov ecx, [eax]
  loc_11001914: call [ecx+00000004h]
  loc_11001917: mov edx, arg_C
  loc_1100191A: lea ecx, var_1C
  loc_1100191D: mov var_18, esi
  loc_11001920: mov var_1C, esi
  loc_11001923: call [1100105Ch] ; %ecx = %S_edx_S '__vbaStrCopy
  loc_11001929: mov edx, var_1C
  loc_1100192C: push edx
  loc_1100192D: push 1100151Ch ; "xyz"
  loc_11001932: call [11001010h] ; @%StkVar2 & %x1 '__vbaStrCat
  loc_11001938: mov edx, eax
  loc_1100193A: lea ecx, var_1C
  loc_1100193D: call [11001080h] ; %ecx = %S_edx_S '__vbaStrMove
  loc_11001943: mov eax, var_1C
  loc_11001946: push eax
  loc_11001947: push 11001528h ; "abcxyz"
  loc_1100194C: call [1100102Ch] ; @(%StkVar2 = %x1) '__vbaStrCmp
  loc_11001952: neg eax
  loc_11001954: sbb eax, eax
  loc_11001956: neg eax
  loc_11001958: dec eax
  loc_11001959: mov var_18, eax
  loc_1100195C: push 1100196Bh
  loc_11001961: lea ecx, var_1C
  loc_11001964: call [11001090h] ; %ecx = "" '__vbaFreeStr
  loc_1100196A: ret
  loc_1100196B: mov eax, arg_8
  loc_1100196E: push eax
  loc_1100196F: mov ecx, [eax]
  loc_11001971: call [ecx+00000008h]
  loc_11001974: mov edx, arg_10
  loc_11001977: mov ax, var_18
  loc_1100197B: mov [edx], ax
  loc_1100197E: mov eax, var_4
  loc_11001981: mov ecx, var_14
  loc_11001984: pop edi
  loc_11001985: pop esi
  loc_11001986: mov fs:[00000000h], ecx
  loc_1100198D: pop ebx
  loc_1100198E: mov esp, ebp
  loc_11001990: pop ebp
  loc_11001991: retn 000Ch
Ta thấy code này có lẽ còn dễ đọc hơn code của function trong file exe ở bài 4, tuy vậy do hợp ngữ mình chỉ ở mức vỡ lòng nên không thể bàn sâu hơn về vấn đề dịch ngược được.
 

tuhocvba

Administrator
Thành viên BQT
Một bài viết có giá trị, hình ảnh minh họa trực quan.
Giờ mời các Mod vào crack các Tool đang treo trong này :
Đầu tiên hãy phá thử pass winrar.
Sau đó biên dịch ngược như nào về code gốc cho mình xem sao.
 

NhanSu

SMod
Thành viên BQT
Tiếp theo, mình đã tạo Standard DLL theo hướng dẫn tại link:
DLL này chỉ chứa hàm checkpass, lại dùng VB decompiler để load file, ta vẫn được code tuơng tự bài 4.
Bạn cần đăng nhập để thấy đính kèm


Mã:
Public Sub Proc_1_0_11001930
  loc_11001966: var_18 = arg_8
  loc_11001980: var_18 = var_18 & "xyz"
  loc_110019A0: eax = (var_18 = "abcxyz") - 1
  loc_110019A1: var_14 = (var_18 = "abcxyz") - 1
End Sub
Mã:
  loc_11001930: push ebp
  loc_11001931: mov ebp, esp
  loc_11001933: sub esp, 00000008h
  loc_11001936: push 110010B6h ; undef 'Ignore this
  loc_1100193B: mov eax, fs:[00000000h]
  loc_11001941: push eax
  loc_11001942: mov fs:[00000000h], esp
  loc_11001949: sub esp, 0000000Ch
  loc_1100194C: push ebx
  loc_1100194D: push esi
  loc_1100194E: push edi
  loc_1100194F: mov var_8, esp
  loc_11001952: mov var_4, 11001098h
  loc_11001959: mov edx, arg_8
  loc_1100195C: lea ecx, var_18
  loc_1100195F: mov var_18, 00000000h
  loc_11001966: call [1100105Ch] ; %ecx = %S_edx_S '__vbaStrCopy
  loc_1100196C: mov eax, var_18
  loc_1100196F: push eax
  loc_11001970: push 11001584h ; "xyz"
  loc_11001975: call [11001010h] ; @%StkVar2 & %x1 '__vbaStrCat
  loc_1100197B: mov edx, eax
  loc_1100197D: lea ecx, var_18
  loc_11001980: call [11001080h] ; %ecx = %S_edx_S '__vbaStrMove
  loc_11001986: mov ecx, var_18
  loc_11001989: push ecx
  loc_1100198A: push 11001590h ; "abcxyz"
  loc_1100198F: call [1100102Ch] ; @(%StkVar2 = %x1) '__vbaStrCmp
  loc_11001995: neg eax
  loc_11001997: sbb eax, eax
  loc_11001999: push 110019AEh
  loc_1100199E: neg eax
  loc_110019A0: dec eax
  loc_110019A1: mov var_14, eax
  loc_110019A4: lea ecx, var_18
  loc_110019A7: call [11001090h] ; %ecx = "" '__vbaFreeStr
  loc_110019AD: ret
  loc_110019AE: mov ecx, var_10
  loc_110019B1: mov ax, var_14
  loc_110019B5: pop edi
  loc_110019B6: pop esi
  loc_110019B7: mov fs:[00000000h], ecx
  loc_110019BE: pop ebx
  loc_110019BF: mov esp, ebp
  loc_110019C1: pop ebp
  loc_110019C2: retn 0004h
 

NhanSu

SMod
Thành viên BQT
Về crack thì mình không làm được. Vấn đề phá mã winrar, mình đã tìm kiếm nhiều lần, chỉ thấy các ứng dụng dò pass bằng kiểu Brute force (vét cạn) thôi.
 
O

OnceMore

Guest
@NhanSu cám ơn bạn đã làm rõ vấn đề giúp mình vấn đề dịch ngược dll và exe.
 

tuhocvba

Administrator
Thành viên BQT
Giờ muốn bẻ tool thì bước 1 phải phá pass winrar . Chẳng lẽ nay liên hệ xin pass mai lên face chửi đổng thì sao còn lần sau nữa .
Bây giờ tool phát hành, nhận tool nhất thiết phải có liên hệ với tác giả . Trường hợp người ta cho nhau pass cũng có nhưng nó nhục nhã vô cùng . Vì giờ phát hành tool chỉ cần chèn thêm cái thông báo tôi không muốn chia sẻ tool cho anh a chị b .
Vì vậy nếu phá được pass win rar thì báo với mình .
 

Euler

Administrator
Thành viên BQT
@NhanSu cám ơn bạn đã làm rõ vấn đề giúp mình vấn đề dịch ngược dll và exe.
Theo bạn sử dụng 1 dll với sử dụng 2 dll gọi chéo nhau, thì cái nào dễ khôi phục code gốc hơn?
Mong Smod có thêm bài về debug .
Giờ kịch bản của admin là vừa sử dụng excel vừa exe vừa dll khi đó debug như nào ?
So với việc sử dụng excel và dll thì cái nào dễ debug hơn .
 
T

thanhphong

Guest
Ta thấy code này có lẽ còn dễ đọc hơn code của function trong file exe ở bài 4
Khi nói đến đây theo em nên có hình ảnh, dễ hơn là dễ hơn ở đâu.
Ví dụ :
Bạn cần đăng nhập để thấy đính kèm

Không biết em nói vậy có đúng không bác nhỉ?
Bác nên chau chuốt bài viết thêm nữa bác ạ.
 
Top