?? 用批處理調用api實現文件下載.txt
字號:
四.解決-實戰
倘若就此編寫一個可下載文件的EXE,然后直接用BAT包裹,定然會被同行恥笑,不單是因為那幾千個字節的數據拖著大大臃腫的BAT文件,更加讓為這種簡單的想法立刻現形,為了不達到這些負面效果,也為了讓這篇文檔不至于干癟癟的讓人感覺沒什么看頭(事實上是因為早些時候看過watercloud的一篇大作感悟頗深),我決定手工寫一串16進制代碼來代替機器編譯的EXE.既美觀了界面,又增強了技術性.....(一_一...簡直是在賣作...)
現在當務之急是要一個可以下載文件的EXE程序,實現這個目標只要一個URLDownloadToFile即可,放在最后實現,先來寫一個PE框架:大家都知道PE文件的格式吧,不懂的就去看看那個著名的電信黑客羅某某的書.(Who!?...~)
先給出我們的PE框架,基于XP的FileAlignment對齊大小最小就支持到0x200(也就是10進制的512字節,以下有在前面加上0x的都表示16進制數值),我們的框架就打出512字節(注意,我下面留有空白表示各個PE部分,結合下面的文檔,大家方便理解),這個框架里沒有任何的代碼或者數據:
(ZV友情提示:下面是最枯燥的部分,各位手握錐子,要有一不怕苦,二不怕痛的精神看完它....)
(如果定力不高的朋友,或者堆PE文件再熟悉不過的朋友,可以字節轉到"JMP S1"處往下看.)
(如果只想知道到底怎么回事,或者對這篇作文報瀏覽態度的朋友,可以直接轉到"JMP S2"處繼續瀏覽)
(睡著了的繼續睡覺....)
代碼
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00000000 4D 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 MZ..............
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 ............@...
==============================================================================
00000040 50 45 00 00 4C 01 02 00 00 00 00 00 00 00 00 00 PE..L...........
00000050 00 00 00 00 70 00 0F 01
0B 01 00 00 00 02 00 00 ....p...........
00000060 00 00 00 00 00 00 00 00 79 01 00 00 00 00 00 00 ........y.......
00000070 00 00 00 00 00 00 40 00 00 10 00 00 00 02 00 00 ......@.........
00000080 00 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 ................
00000090 00 30 00 00 00 02 00 00 00 00 00 00 02 00 00 00 .0..............
000000A0 00 01 00 00 00 00 00 00 00 01 00 00 00 10 00 00 ................
000000B0 00 00 00 00 02 00 00 00
00 00 00 00 00 00 00 00 ................
000000C0 28 11 00 00 28 00 00 00
==============================================================================
00 00 00 00 00 00 00 00 (...(...........
000000D0 00 02 00 00 00 10 00 00 00 02 00 00 00 01 00 00 ................
000000E0 00 00 00 00 00 00 00 00 00 00 00 00 60 00 00 60 ............`..`
000000F0 00 00 00 00 00 00 00 00 02 00 00 00 00 20 00 00 ............. ..
00000100 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110 00 00 00 00 60 00 00 60 00 00 00 00 00 00 00 00 ....`..`........
00000120 58 11 00 00 00 00 00 00 50 11 00 00 00 00 00 00 X.......P.......
00000130 00 00 00 00 6E 11 00 00 20 11 00 00 00 00 00 00 ....n... .......
00000140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150 58 11 00 00 00 00 00 00
00 00 00 00 00 00 00 00 ................
00000160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
這里簡單介紹一下PE文件格式的組成:
大致來分呢,PE格式文件可以分為這三個部分(就是上述框架中用"=="分割的三個部分):
引用
++++++++++++++++++++++++
+DOS信息部分 +
++++++++++++++++++++++++
++++++++++++++++++++++++
+PE信息部分 +
++++++++++++++++++++++++
++++++++++++++++++++++++
+數據部分 +
++++++++++++++++++++++++
下面來簡單介紹每一部分的結構,首先的"DOS信息部分":
引用
+++++++++++++++++++++++++++++++++++++++++++++
+ +++++++++++++++++++++++++++++++++++++++ +
+ +[DOS文件頭][0x40] + +
+ +++++++++++++++++++++++++++++++++++++++ +
+ + <==DOS信息部分
+ +++++++++++++++++++++++++++++++++++++++ +
+ +[DOS塊][0x70,可變] + +
+ +++++++++++++++++++++++++++++++++++++++ +
+++++++++++++++++++++++++++++++++++++++++++++
這部分我覺得是最冗余的地方,首先DOS文件頭的結構:
代碼
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
其中最重要的就是e_lfanew,它指向了下面的"PE信息部分"的起始地址(也就是俗稱的PE頭部).其他的是一些DOS下運行這個PE文件必須的結構,比如看注解就明白,什么代碼初始化堆棧段,初始化堆棧指針,入口IP,CS等等,都是在WIN32上沒有用的東西,我就不翻譯拉,這些都是說DOS下的,如果這個PE文件一開始就打定在WINDOWS下運行,這些亂寫都無所謂,你甚至可以把你的名字都寫進去(.....一_一..).當然,你這么作后這個文件就不能在DOS下運行了..不然當機是幾乎可以肯定的....(寒....).
需要記的除了e_lfanew是指向PE頭的指針外還要記得這個DOS文件頭結構長0x40,也就是64個字節.還有第一個參數e_magic,這個地方永遠是"0x40 0x5a",也就是字符的"MZ".
DOS塊部分保存的就是一段DOS下可以執行的代碼,比如現在大多編譯器就簡單的輸出一個"This program cannot be run in DOS mode"的字符串,和"DOS信息部分"一樣,如果你不打算在DOS執行這個EXE文件,那么這里完全可以刪除,為什么?因為WIN32的PE裝載器只關心"DOS信息部分"的e_lfanew指向的而已.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -