首页
社区
课程
招聘
[原创]可執行檔編碼程式 (.COM 篇)
发表于: 2009-4-14 16:18 4355

[原创]可執行檔編碼程式 (.COM 篇)

2009-4-14 16:18
4355

有人看了二, 要我把一也發上來. 努力一找, 還真找到了.
這個技巧一不是破解, 而是保護 CRYPTCOM.ASM  可執行檔編碼器 (.COM 格式)  的編寫教學.
也就是 FSE 的原型.   附件是編排好一點的 PDF.

    ┌───────────────────────────────┐
    │ 個人基本資料                                                 │
    ├───────────────────────────────┤
    │ 姓名      : 楊旭峰                                           │
    │ 身份證字號: **********                                       │
    │ 通訊地址  : *********************************************    │
    │ 戶籍地址  : ***********************************              │
    │ 聯絡電話  : (**)***-**** (公司)                              │
    │             (**)***-**** (家裡)                              │
    └───────────────────────────────┘

以上為投稿內容:
本文件內容為 PE2 所打, 未經重新編排修飾.
如蒙採用, 我每個月寫個兩三篇也沒問題....
╒═════╤═══════════════════════════════
│[技術空間]│
╘═════╛

   保護與破解的攻防技巧(一):

   可執行檔編碼程式 (.COM 篇)

                                                            / 楊旭峰
                                                zenix@ms10.hinet.net

        再過幾天就是聖誕節了, 為了和他共渡一段浪漫的假期, 決定儘早把
    這份電腦作業給完成. 我可不希望在浪漫的時刻還在擔心作業交不出來啊!

        真是一個殘酷的聖誕節, 趕剛完的程式還未打上註解, 哦! 明天還要
    上台報告. 時間為什麼總是不夠用? 知識總是學不完.

        回想當初為什麼會寫這個程式呢? 記得從玩電腦開始, 最可怕的工具軟
    體就是 PcTools. V4.XX 版, 相信今天用它的人還很多. 這一類的軟體可
    以讓使用者輕易地修改任何檔案內容. 功力好的人就拿來修改程式碼, 以
    破解軟體的保護, 功力差的人也能利用它來輕易地修改版權畫面. 而當時
    功力差的人居多, 因此隨處可見被篡改的版權畫面. 真不知他們這樣子做
    的樂趣在哪裡?

        有一天出現了一種叫做可執行檔壓縮器. 這種工具軟體可以把可執行
    檔壓縮, 而且壓縮後的檔案仍然可以正常執行. 更令軟體商心動的是, 壓
    縮後的檔案內容是編碼過的, 和原來內容不一樣, 似乎可以有效地防止被人
    『輕易』地篡改. 但是用過的人都知道壓縮檔的內容並未完全加密, 因此
    很多時候部份的檔案內容是和原來相同的. 所以如果我們真正需要的是完
    全編碼而非部份編碼的話, 那麼我們何不來自己做一個編碼器?

        可執行檔編碼器在以前真可謂是『不傳之秘』. 連原理都沒有人願意
    透露, 原因我想大家多少也都知道一些吧! 在此我們先就 .COM 檔來做一
    個編碼器! 在開始之前, 我們必須先來了解一下 .COM 檔. 在此我並不打算
    探入探討像 PSP結構之類的問題, 僅告訴你我們需要的最基本概念即可.

      ┌───────────────────┐
      │.COM 檔的特性:                        │
      ├───────────────────┤
      │(1). 程式載入時: CS=DS=ES=SS          │
      │                 IP=100h              │
      │                 SP=FFFE              │
      │(2). 檔案長度小於 64 K (10000h Byte)  │
      │(3). 沒有檔頭, 也沒有重定位表.        │
      └───────────────────┘

        接下來我們該怎麼著手呢? 先看看一般病毒的作法吧! 如果我們大略
    地看一下被感染檔案的程式碼, 它是像這個樣子.
       ┌────────────────────────────┐
       │Start:                                                  │
       │        jmp  Virus    ;; 原來這裡的 3 Byte 被改成這樣   │
       │        .....                                           │
       │        .....  這裡是原程式                             │
       │        .....                                           │
       │Virus:                                                  │
       │        做病毒該做的事 以及 還原最前面的 3 Byte         │
       │        回到 Start                                      │
       └────────────────────────────┘

        病毒為了減少磁碟寫入時間, 會先保留原程式最開頭的 3 - 4 Byte,
        然後僅寫入最開頭的 jmp virus 或 call virus, 然後在 virus 的程式
        碼中再還原程式的最開頭. 可是我們可以不必這麼做.

        為求一切從簡, 我們決定把我們編碼器做出來的檔案分成三部份:
        [跳躍指令(到解碼段)] + [編碼過後的原程式] + [解碼及返回]

        格式訂定如下:
         ┌────────────────────┐
         │Start:                                  │
         │        pusha       ;; 保留暫存器的值   │
         │        jmp Decoder                     │
         │        .....                           │
         │        .....  這裡是編碼過後的原程式   │
         │        .....                           │
         │Decoder:                                │
         │        解碼                            │
         │        popa        ;; 還原暫存器的值   │
         │        回到 Start                      │
         └────────────────────┘

        第一部份『jmp Decoder』, 組譯後的程式碼為 0e9h, ????h.
    但這 ????h 的值是多少呢? 沒錯, 就是原程式的總長度.

        第三部份的最後『回到 Start』, 我們要怎麼做呢? 我們知道Start的
    IP值為 100h, 如果我們不要變動任何節區暫存器的話, 那麼我們可以簡單
    地用這兩行來返回 Start
               ┌─────┐
               │push 100h │
               │ret       │
               └─────┘
    再來是解碼部份. 這一部份我們一定要和編碼部份配合, 否則解不回原來
    的碼就糟糕了. 在編碼及解碼方面, 這一次我們使用 XOR 來做.因為一個
    數對另一個值做 XOR 運算兩次的結果會回到原來的值. 底下就是我們寫好
    的第一個可執行檔編碼器:

>> ======== 從下一行開始 ==========

;; ┌─────────────────────────────╖
;; │檔名: CRYPTCOM.ASM  可執行檔編碼器 (.COM 格式)            ║
;; │版本: 1.0                                                 ║
;; │日期: 1997-12-20                                          ║
;; │組譯: TASM     CRYPTCOM.ASM                               ║
;; │      TLINK /t CRYPTCOM                                   ║
;; │                                                          ║
;; │作者: 楊旭峰 Zenix Yang   zenix@ms10.hinet.net            ║
;; ╘═════════════════════════════╝
        .MODEL TINY
        .CODE
        .286c

        ORG 100h
Start:
        call  Show_Logo              ;; 顯示標題
        call  Open_Input_File        ;; 開啟 IN.COM
        call  Create_Output_File     ;; 建立 OUT.COM
        call  Read_Body              ;; 讀取 IN.COM 的內容
        call  Encrypt_Body           ;; 對所讀取的內容編碼
        call  Write_Output_File      ;; 產生編碼後的 OUT.COM
        jmp   End_All                ;; 結束了
;;--------------------------------------------
;; 顯示標題
;;--------------------------------------------
Show_Logo PROC near
         mov  ah, 09h
         mov  dx, OFFSET msg_Logo
         int  21h
         ret
endp
;;--------------------------------------------
;; 開啟 IN.COM
;;--------------------------------------------
Open_Input_File PROC near
        mov  ah, 3dh
        mov  al, 0h                ;; AL=0, 以唯讀方式開啟檔案
        mov  dx, OFFSET input_file
        int  21h
        jc   Error_Open            ;; 開啟檔案失敗嗎?
        mov  input_handle, ax      ;; 把 IN.COM 的檔案代碼存起來
        ret
    ;; --------------------------------
    ;;  開啟或建立檔案失敗了就來這裡
    ;; --------------------------------
    Error_Open:
        mov  ah, 09h
        mov  dx, OFFSET msg_error_open
        int  21h
        mov  ah, 4ch
        int  21h
endp
;;--------------------------------------------
;; 建立 OUT.COM
;;--------------------------------------------
Create_Output_File PROC near
        mov  ah, 3ch
        mov  cx, 0h
        mov  dx, OFFSET output_file
        int  21h
        jc   error_open           ;; 建立檔案失敗嗎?
        mov  output_handle, ax    ;; 把 OUT.COM 的檔案代碼存起來
        ret
endp
;;--------------------------------------------
;; 讀取 IN.COM 的內容
;;--------------------------------------------
Read_Body PROC near
        mov  ah, 3fh
        mov  cx, 0F000h               ;; 我們這裡只處理長度小於
                                      ;; 61,440 (0F000h) byte 的檔案
        mov  dx, OFFSET Encrypted_Body
        mov  bx, input_handle
        int  21h
        mov  Body_Length, ax   ;; 把檔案長度存起來
        ret
endp
;;--------------------------------------------
;; 對讀取的內容編碼
;;--------------------------------------------
Encrypt_Body PROC near
        mov  cx, Body_Length
        mov  bx, OFFSET Encrypted_Body
   encrypt_loop:
        xor  byte ptr [bx], cl
        inc  bx
        loop encrypt_loop
        ret
endp
;;--------------------------------------------
;; 產生編碼後的 OUT.COM
;;--------------------------------------------
write_output_file PROC near
        mov    ax, body_length            ;;
        mov    word ptr First_Jump+2, ax  ;; 製造 jmp Decoder 程式碼
        mov    word ptr Decoder+1, ax     ;; 製造 mov cx, 檔案長度

        ;; ---------------------------------------------
        ;; 寫入 OUT.COM 的第一部份 [跳躍指令(到解碼段)]
        ;; ---------------------------------------------
        mov    cx, (OFFSET End_First_Jump) - (OFFSET First_Jump)
        mov    dx, OFFSET First_Jump
        call   Write_File

        ;; ---------------------------------------------
        ;; 寫入 OUT.COM 的第二部份 [編碼過後的原程式]
        ;; ---------------------------------------------
        mov    cx, Body_Length
        mov    dx, OFFSET Encrypted_Body
        call   Write_File

        ;; ---------------------------------------------
        ;; 寫入 OUT.COM 的第三部份 [解碼及返回]
        ;; ---------------------------------------------
        mov    cx, (OFFSET End_Decoder) - (OFFSET Decoder)
        mov    dx, OFFSET Decoder
        call   Write_File
        ret

    ;;--------------
    Write_File:
        mov  ah, 40h
        mov  bx, output_handle
        int  21h
    ret
endp

;;--------------------------------------------
;; 結束了
;;--------------------------------------------
End_all:
         mov  bx, input_handle      ;;
         mov  ah, 3eh               ;;
         int  21h                   ;; 關閉 IN.COM

         mov  bx, output_handle     ;;
         mov  ah, 3eh               ;;
         int  21h                   ;; 關閉 OUT.COM

         mov  dx, OFFSET msg_Thanks ;;
         mov  ah, 09h               ;;
         int  21h                   ;; 結束的訊息

         mov  ah, 4ch               ;;
         int  21h                   ;; 程式結束

;;--------------------------------------------
;; 這裡放一些我們要用到的資料
;;--------------------------------------------
input_file     DB 'IN.COM',0      ;;  要編碼的檔案名稱
output_file    DB 'OUT.COM',0     ;;  編碼後的檔案名稱

input_handle   DW 0               ;;  IN.COM  的檔案處理代碼
output_handle  DW 0               ;;  OUT.COM 的檔案處理代碼

body_length    DW 0               ;;  IN.COM 的檔案長度

    ;;------------------
    ;; 標題
    ;;------------------
msg_logo   DB 0Ah, 0Dh
           DB "---== My First and Simple .COM Encryptor  V0.1 ==---",0ah, 0dh
           DB "------------------------...[ZeNiX of pCE '98]...----",0ah, 0dh
           DB " ... Encrypts IN.COM into OUT.COM",0ah, 0dh
           DB 0Ah, 0dh, '$'

    ;;------------------
    ;; 訊息: 錯誤發生
    ;;------------------
msg_error_open   DB 'Error!', 0AH, 0DH, '$'
    ;;------------------
    ;; 訊息: 編碼成功
    ;;------------------
msg_Thanks       DB 'File: IN.COM was encrypted to OUT.COM', 0AH, 0DH, '$'

;;--------------------------------------------
;; 這裡是 OUT.COM 要用到的程式碼
;;--------------------------------------------
        ;; ----------------------------------------
        ;; OUT.COM 的第一部份 [跳躍指令(到解碼段)]
        ;; ----------------------------------------
First_Jump:
            pusha
            db   0e9h ;; 我們會把這裡改成 OUT.COM 的 jmp Decoder
            DW   0    ;;
End_First_Jump:
        ;; ---------------------------------
        ;; OUT.COM 的第三部份 [解碼及返回]
        ;; ---------------------------------
Decoder:
          mov  cx, 0  ;; 我們會把這裡改成 OUT.COM 的 mov cx, 解碼長度
          mov  si, (OFFSET End_First_Jump) - (OFFSET First_Jump)
          mov  di, 100h
          add  si, di

          ;; -----
          ;; 解碼
          ;; -----
  Decrypt_Loop:
          lodsb
          xor  al, cl
          stosb
          loop Decrypt_Loop

          popa
          push  100h  ;; 返回位址為 IP=100h
          ret
End_Decoder:

        ;; --------------------------------------
        ;; OUT.COM 的第二部份 [編碼過後的原程式]
        ;; --------------------------------------
Encrypted_Body:

end Start

>> ======== 在上一行結束 ==========

      再來我們希望加上一些反追蹤技巧, 所以把上面程式 OUT.COM 的第三部份
  [解碼及返回] 改成如下, 這樣一來如果我們就無法使用 Debug, Symdeb
  甚至 Soft-ICE 的 LDR.EXE 載入 OUT.COM 來追蹤程式了.
  至於原理, 我們就留待下回再分析了.

>> ======== 從下一行開始 ==========
        ;; ---------------------------------
        ;; OUT.COM 的第三部份 [解碼及返回]
        ;; ---------------------------------
Decoder:
          mov  cx, 0  ;; 我們會把這裡改成 OUT.COM 的 mov cx, 解碼長度
          mov  ax, ds
          and  ax, dx
          mov  ds, ax
          mov  es, ax
          mov  di, si
          add  si, (OFFSET End_First_Jump) - (OFFSET First_Jump)

          ;; -----
          ;; 解碼
          ;; -----
  Decrypt_Loop:
          lodsb
          xor  al, cl
          stosb
          loop Decrypt_Loop

          popa
          push  100h  ;; 返回位址為 IP=100h
          ret
End_Decoder:

>> ======== 在上一行結束 ==========

   最後附上 CRYPTCOM.COM 有加入反追蹤技巧的版本. 您可以用下列的方法把
   程式還原: (如果你沒有 TASM 的話.)

   DEBUG.EXE < CRYPTCOM.ASC

>> ======== 從下一行開始 ==========
N CRYPTCOM.COM
E 0100 e8 12 00 e8 17 00 e8 2e 00 e8 3b 00 e8 4a 00 e8 54 00 e9 80 00 b4 09
E 0117 ba c5 01 cd 21 c3 b4 3d b0 00 ba b0 01 cd 21 72 04 a3 bf 01 c3 b4 09
E 012e ba 59 02 cd 21 b4 4c cd 21 b4 3c b9 00 00 ba b7 01 cd 21 72 e9 a3 c1
E 0145 01 c3 b4 3f b9 00 f0 ba a9 02 8b 1e bf 01 cd 21 a3 c3 01 c3 8b 0e c3
E 015c 01 bb a9 02 30 0f 43 e2 fb c3 a1 c3 01 a3 8c 02 a3 8f 02 b9 04 00 ba
E 0173 8a 02 e8 14 00 8b 0e c3 01 ba a9 02 e8 0a 00 b9 1b 00 ba 8e 02 e8 01
E 018a 00 c3 b4 40 8b 1e c1 01 cd 21 c3 8b 1e bf 01 b4 3e cd 21 8b 1e c1 01
E 01a1 b4 3e cd 21 ba 62 02 b4 09 cd 21 b4 4c cd 21 49 4e 2e 43 4f 4d 00 4f
E 01b8 55 54 2e 43 4f 4d 00 00 00 00 00 00 00 0a 0d 2d 2d 2d 3d 3d 20 4d 79
E 01cf 20 46 69 72 73 74 20 61 6e 64 20 53 69 6d 70 6c 65 20 2e 43 4f 4d 20
E 01e6 45 6e 63 72 79 70 74 6f 72 20 20 56 30 2e 31 20 3d 3d 2d 2d 2d 0a 0d
E 01fd 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d
E 0214 2d 2e 2e 2e 5b 5a 65 4e 69 58 20 6f 66 20 70 43 45 20 27 39 38 5d 2e
E 022b 2e 2e 2d 2d 2d 2d 0a 0d 20 2e 2e 2e 20 45 6e 63 72 79 70 74 73 20 49
E 0242 4e 2e 43 4f 4d 20 69 6e 74 6f 20 4f 55 54 2e 43 4f 4d 0a 0d 0a 0d 24
E 0259 45 72 72 6f 72 21 0a 0d 24 46 69 6c 65 3a 20 49 4e 2e 43 4f 4d 20 77
E 0270 61 73 20 65 6e 63 72 79 70 74 65 64 20 74 6f 20 4f 55 54 2e 43 4f 4d
E 0287 0a 0d 24 60 e9 00 00 b9 00 00 8c d8 23 c2 8e d8 8e c0 8b fe 83 c6 04
E 029e ac 32 c1 aa e2 fa 61 68 00 01 c3
RCX
01a9

w
q

>> ======== 在上一行結束 ==========

╒═════╤═══════════════════════════════
│[文件結束]│
╘═════╛
                                                            / 楊旭峰
                                                zenix@ms10.hinet.net


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//