VC 下編譯出極小的程式

2021-04-18 14:51:50 字數 3159 閱讀 7273

昨天做了個telnet後門程式玩, 既然是後門嘛,自然是越小越好.可是我的vc9編譯乙個helloworld都有50k+... 動態鏈結到msvcrt90.dll倒是小下來了,但是得背上乙個更**的dll(600多k) 而這個msvcrt90.dll就是我的vista sp1也不是自帶的.更不便於程式的部署. 最後自己去查了查資料終於編譯出體積比較滿意的exe,步驟如下: 1.扔掉crt. crt提供了大量常用的函式.可說只要c/c++程式基本都會用到它.但是獲得了方便的同 時也增大了不少體積.雖然可以通過動態鏈結到外部的dll來解決,但是自此就有了對一 個更大的dll的依賴.所以要**,就要先拿crt開刀. 在cl的編譯引數中加上/md,再在link中加上/nodefaultlib:msvcrt.lib即可避免鏈結 到crt(靜態crt的lib檔名我不清楚,所以就先鏈結成動態的,再去除對應的msvcrt.lib) 2.過載new,new,delete,delete c/c++程式少不了動態分配記憶體,前面丟掉了crt,再編譯程式會發現反是有記憶體分配的地方都 在報錯,這是因為我去掉了crt,編譯器找不到對應的函式所致.所以要自己寫記憶體分配函式. c的malloc和c++的new/new都是在當前的堆上分配記憶體.所以只要照著寫一遍就可以了:

c/c++ code

typedef uint size_t; 

void

*malloc(size_t size)

void

free (

void

*memblock)

void

*realloc(

void

*memblock,size_t size)

void

*operator

new(size_t count)

void

*operator

new(size_t count)

void

operator

delete(

void

*_ptr)

throw

( )

void

operator

delete(

void

*_ptr)

throw

( )

3.常用函式的替代. 沒了crt許多常用的函式都無法使用,全部自己重寫無疑大大加大了程式的代 碼量,也沒多大意義.windows提供了很多常用的函式.都由系統的dll來提供, 使用它們就不用 a 字串處理函式.   字串處理函式的替代品很多,kernel32.dll提供了lstr***的函式.完全 可以滿足字串處理的需要,c的格式化字串sprintf函式很好用,而user32.dll 也提供了相應的函式wsprintf/wvsprintf用於替代.沒有字串查詢函式有點麻煩 不過自己寫也要不了幾行**,或者乾脆用shlwapi.dll提供的更完整的字串處理 庫來替代. b 命令列輸入/輸出函式.   這個...系統還真沒提供啥對應的函式,不過好在常用也不是太複雜.用console api寫 幾條常用的getline和puts就足夠了. 4.重新指定入口點.   如果問vc程式的入口點是什麼,估計會有不少人回答是main/winmain. 沒錯.這是使用了標準的crt的程式的入口點.但是實際的入口函式是crt內部編寫好的.在 完成庫的初始化後再呼叫main/winmain.既然移除了crt,鏈結器自然就會發出找不到入口 函式的錯誤,解決方法很簡單,用/entry:指定乙個函式就可以了.我仍然用習慣的main. 但是注意,這個main不能帶任何的引數.帶了也用不了. 5.更改節的對齊大小. cl編譯器預設的對齊大小是4k(4096)這個數值的設定是個問題.有時候會使編譯出來的程式無 法執行.這個只有自己反覆的試驗了.我將它設定為512(其實還可以更小,但是小於512的程式不能使用upx壓縮)程式又小了幾k. 6.給exe加殼. 使用exe加殼程式給程式加個殼也是減小體積的乙個好方法. 我常用的是upx,如果前面的節對齊的值大於512的話,就可以使用upx進行加殼壓縮. 通常可以壓縮至原大小的66%左右. 7.折中的辦法: 丟掉了crt,重寫一些函式的工作量比較大,而且有些函式自己也寫不出來.(比如sin函式,像我這樣的 高數菜鳥拿著就頭痛)但確實有時候會用到這些函式.於是就有了以下的折中辦法: vc6是98年推出的.它的動態鏈結庫版的dll是msvcrt.dll,因為出來的早,這個dll的裝機率十分的高. (我以前學校的win98se都自帶,98後的系統自然不用說了.)使用它基本可以不考慮部署時缺少dll的問題 所以可以使用這個dll提供的crt函式.要使用它,先得去找個vc6,複製裡面的msvcrt.lib,改個名.比如 vcrt6.lib然後把它新增到鏈結的庫里.編譯的時候會有庫衝突的提示,直接無視即可.這樣既可以使用絕大 部分的crt庫,又做到了**.還不用擔心會有找不到庫的情況.也不用再重新指定入口點.但是經我試驗發現 這樣編譯出來的程式還是會比完全丟掉crt的大上一點,所以只是個折中的辦法. 接下來做下試驗: 寫乙個簡單的程式:

c/c++ code

#include 

<

windows.h

>

#include

<

stdio.h

>

void

main ()

然後做下編譯(vc9的編譯器,未更改節對齊值,未做加殼) 靜態crt:50kb 動態鏈結crt:5.50kb 使用vc6的動態鏈結crt:3.00 kb 完全不用crt要做下更改:

c/c++ code

#include 

<

windows.h

>

#pragma

comment (lib,"user32.lib")

#pragma

comment (lib,"kernel32.lib")

void

*operator

new (unsigned

intsize)

void

operator

delete (

void

*memblock)

#define

sprintf wsprintf

void

main ()

編譯引數也比較長: cl /md msgbox.cpp /link /nodefaultlib:msvcrt.lib /entry:main 編譯後大小:2.00kb 加上/align:16編譯後大小:960byte

winpcap網路程式設計在vc6下編譯出錯的原因

winpcap 4.1.1在vc6下編譯會出現以下錯誤,原因是vc6.0並不完美支援c 99標準,在64位cpu中編譯會有問題,將winpcap開發包換到4.0.1版本及以下錯誤消失 c wpdpack include pcap stdinc.h 79 error c2144 syntax erro...

編譯出錯 程式中有游離的 302

編者按 複製別人的 到linux中執行,在編譯時出錯 錯誤 程式中有游離的 302 查詢資料後獲取解決方法,在此做乙個記錄。錯誤提示如下 read.c 164 6 錯誤 程式中有游離的 302 read.c 164 6 錯誤 程式中有游離的 302 read.c 164 6 錯誤 程式中有游離的 3...

使用VC2005編譯出現這個錯誤

include unknwn.idl 108 error midl2025 syntax error expecting or near annotation include unknwn.idl 108 error midl2026 cannot recover from earlier synt...