程序破解及ELF文件格式分析

程序破解

NOP天吓、JNE贿肩、JE、JMP龄寞、CMP匯編指令的機(jī)器碼

NOP:NOP指令即“空指令”汰规。執(zhí)行到NOP指令時(shí),CPU什么也不做物邑,僅僅當(dāng)做一個(gè)指令執(zhí)行過去并繼續(xù)執(zhí)行NOP后面的一條指令溜哮。(機(jī)器碼:90)

JNE:條件轉(zhuǎn)移指令,如果不相等則跳轉(zhuǎn)色解。(機(jī)器碼:75)

JE:條件轉(zhuǎn)移指令茂嗓,如果相等則跳轉(zhuǎn)。(機(jī)器碼:74)

JMP:無條件轉(zhuǎn)移指令科阎。段內(nèi)直接短轉(zhuǎn)Jmp short(機(jī)器碼:EB)段內(nèi)直接近轉(zhuǎn)移Jmp near(機(jī)器碼:E9)段內(nèi)間接轉(zhuǎn)移Jmp word(機(jī)器碼:FF)段間直接(遠(yuǎn))轉(zhuǎn)移Jmp far(機(jī)器碼:EA)

CMP:比較指令述吸,功能相當(dāng)于減法指令承桥,只是對(duì)操作數(shù)之間運(yùn)算比較京办,不保存結(jié)果。cmp指令執(zhí)行后,將對(duì)標(biāo)志寄存器產(chǎn)生影響沃饶。其他相關(guān)指令通過識(shí)別這些被影響的標(biāo)志寄存器位來得知比較結(jié)果。

反匯編與十六進(jìn)制編程器

實(shí)驗(yàn)源碼:

login.c

#include<stdio.h>
void main()
{
        int pass=123;
        int enter;
        printf("please enter the password:\n");
        scanf("%d",&enter);
        if(enter==pass)
                printf("right\n");
        else
                printf("wrong\n");
}

運(yùn)行效果如下:

輸入命令:

objdump -d login

查看main函數(shù)

現(xiàn)在的需求是:修改可執(zhí)行文件另其無論輸入什么密碼的是正確的疙剑。

修改思路:將jne 跳轉(zhuǎn)偏移量改為0先煎,這樣40063a位置的指令就相當(dāng)于繼續(xù)執(zhí)行輸出right。

實(shí)現(xiàn)方法:

輸入指令:

vim login

打開可執(zhí)行文件

輸入:

%!xxd

進(jìn)入十六進(jìn)制編輯模式茅逮,如下圖所示:

然后輸入

/750c

找到j(luò)ne指令的位置璃赡,如下圖所示:

將750c改成7500表示跳轉(zhuǎn)到下一條指令繼續(xù)執(zhí)行,相當(dāng)于NOP氮唯。

輸入

%!xxd -r

切換回原模式

輸入

wq

保存后退出鉴吹。

運(yùn)行修改后的文件效果如下:

由圖可見無論輸入什么密碼都是正確的,修改成功惩琉。

如果想輸入什么密碼都是錯(cuò)誤的豆励,只需要將750c改為eb0c即可,eb為JMP瞒渠,0c為輸出"wrong"的代碼相對(duì)偏移量良蒸。

效果如下:

如果想輸入原先正確的密碼為"wrong",輸出其他密碼為"right",只需把750c改為740c即可伍玖,74相當(dāng)于JE嫩痰,相等則跳轉(zhuǎn)。

效果如下:

可執(zhí)行文件的基本格式

Linux可執(zhí)行文件格式為ELF即Executable and Linkable Format窍箍。

格式:

ELF header :ELF文件頭串纺,在文件的開始,保存了路線圖椰棘,描述了該文件的組織情況纺棺。

program header table :程序文件頭表,告訴系統(tǒng)如何創(chuàng)建進(jìn)程映像邪狞。用來構(gòu)造進(jìn)程映像的目標(biāo)文件必須具有程序頭部表祷蝌,可重定位文件不需要這個(gè)表。

.text段:存儲(chǔ)只讀程序

.data段:存儲(chǔ)已經(jīng)初始化的全局變量和靜態(tài)變量

.bss段:存儲(chǔ)未初始化的全局變量和靜態(tài)變量帆卓,因?yàn)檫@些變量的值為0巨朦,所以這個(gè)段在文件當(dāng)中不占據(jù)空間

.rodata段:存儲(chǔ)只讀數(shù)據(jù),比如字符串常量

...(各種(節(jié)))

Section header table:節(jié)頭部表剑令,包含了描述文件節(jié)區(qū)的信息糊啡,每個(gè)節(jié)區(qū)在表中都有一項(xiàng),每一項(xiàng)給出諸如節(jié)區(qū)名稱尚洽、節(jié)區(qū)大小這類信息悔橄。用于鏈接的目標(biāo)文件必須包含節(jié)區(qū)頭部表,其他目標(biāo)文件可以有,也可以沒有這個(gè)表癣疟。

具體分析見ELF文件格式分析挣柬。

ELF文件格式分析

ELF全稱Executable and Linkable Format,可執(zhí)行連接格式,ELF格式的文件用于存儲(chǔ)Linux程序睛挚。ELF文件(目標(biāo)文件)格式主要三種:

1)可重定向文件:文件保存著代碼和適當(dāng)?shù)臄?shù)據(jù)邪蛔,用來和其他的目標(biāo)文件一起來創(chuàng)建一個(gè)可執(zhí)行文件或者是一個(gè)共享目標(biāo)文件。(目標(biāo)文件或者靜態(tài)庫文件扎狱,即linux通常后綴為.a和.o的文件)

2)可執(zhí)行文件:文件保存著一個(gè)用來執(zhí)行的程序侧到。(例如bash,gcc等)

3)共享目標(biāo)文件:共享庫淤击。文件保存著代碼和合適的數(shù)據(jù)匠抗,用來被下連接編輯器和動(dòng)態(tài)鏈接器鏈接。(linux下后綴為.so的文件污抬。)

ELF文件頭

查看/usr/include/elf.h中的ELF頭文件數(shù)據(jù)結(jié)構(gòu)汞贸。

#define EI_NIDENT (16)

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf64_Half    e_type;                 /* Object file type */
  Elf64_Half    e_machine;              /* Architecture */
  Elf64_Word    e_version;              /* Object file version */
  Elf64_Addr    e_entry;                /* Entry point virtual address */
  Elf64_Off     e_phoff;                /* Program header table file offset */
  Elf64_Off     e_shoff;                /* Section header table file offset */
  Elf64_Word    e_flags;                /* Processor-specific flags */
  Elf64_Half    e_ehsize;               /* ELF header size in bytes */
  Elf64_Half    e_phentsize;            /* Program header table entry size */
  Elf64_Half    e_phnum;                /* Program header table entry count */
  Elf64_Half    e_shentsize;            /* Section header table entry size */
  Elf64_Half    e_shnum;                /* Section header table entry count */
  Elf64_Half    e_shstrndx;             /* Section header string table index */
} Elf64_Ehdr;

                                        

取一段簡單的代碼進(jìn)行分析:

hello.c

#include<stdio.h>
void main()
{
        printf("hello");
}

輸入指令

readelf -h hello

得到ELF文件頭信息:

由圖可看出ELF文件頭大小為64字節(jié)。

輸入命令:

hexdump -x hello -n 64

對(duì)ELF頭的16進(jìn)制表進(jìn)行分析:

第一行對(duì)應(yīng)e_ident[EI_NIDENT],實(shí)際內(nèi)容為:7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 ,前四個(gè)字節(jié)7f454c46(0x45,0x4c,0x46是'e','l','f'對(duì)應(yīng)的ascii編碼)是一個(gè)魔數(shù)印机,表示這是一個(gè)ELF對(duì)象矢腻。接下來02字節(jié)表示是一個(gè)64位對(duì)象,接下來01字節(jié)表示是小端法表示射赛,再接下來的01字節(jié)表示文件頭的版本多柑。剩下的默認(rèn)設(shè)置為0。

第二行楣责,e_type值為0x0002,表示是一個(gè)可執(zhí)行文件竣灌。e_machine的值為0x003e表示目標(biāo)文件所期待的系統(tǒng)架構(gòu)為Advanced Micro Devices X86-64。e_version值為0x00000001秆麸,表示是當(dāng)前版本帐偎。e_entry的值為0x00400430表示程序入口地址。

第三行蛔屹,e_phoff的值為0x0040,表示程序頭部表的起始位置在磁盤文件中的偏移量為64字節(jié)豁生。e_shoff的值為0x19d8,表示節(jié)頭部表(Section Header Table)的起始位置在磁盤文件中的偏移量為6616字節(jié)兔毒。

第四行,e_flags的值為e_flags值為0x00000000甸箱,表示未知處理器特定標(biāo)志育叁。e_ehsize值為0x0040表示ELF文件頭部的大小為64字節(jié)。e_phentsize的值為0x0038,表示程序頭部表(Program Header Table)中每一個(gè)表項(xiàng)的大小56字節(jié)芍殖。e_shnum值為0x0009,表示程序頭部表(Program Header Table)中總共有9個(gè)表項(xiàng)豪嗽。e_shentsize的值為0x0040,表示節(jié)頭部表(Section Header Table)中每一個(gè)表項(xiàng)的大小為64字節(jié)。e_shnum值為0x001f龟梦,表示節(jié)頭部表(Section Header Table)中總共有31個(gè)表項(xiàng)隐锭。e_shstrndx的值為:0x001c表示節(jié)頭部表(Section Header Table)中與節(jié)名字表相對(duì)應(yīng)的表項(xiàng)的索引。

通過文件頭找到section header table计贰,理解其內(nèi)容

在/usr/include/elf.h中section header table的數(shù)據(jù)結(jié)構(gòu)定義如下:

typedef struct
{
  Elf32_Word    sh_name;                /* Section name (string tbl index) */
  Elf32_Word    sh_type;                /* Section type */
  Elf32_Word    sh_flags;               /* Section flags */
  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
  Elf32_Off     sh_offset;              /* Section file offset */
  Elf32_Word    sh_size;                /* Section size in bytes */
  Elf32_Word    sh_link;                /* Link to another section */
  Elf32_Word    sh_info;                /* Additional section information */
  Elf32_Word    sh_addralign;           /* Section alignment */
  Elf32_Word    sh_entsize;             /* Entry size if section holds table */
} Elf32_Shdr;

typedef struct
{
  Elf64_Word    sh_name;                /* Section name (string tbl index) */
  Elf64_Word    sh_type;                /* Section type */
  Elf64_Xword   sh_flags;               /* Section flags */
  Elf64_Addr    sh_addr;                /* Section virtual addr at execution */
  Elf64_Off     sh_offset;              /* Section file offset */
  Elf64_Xword   sh_size;                /* Section size in bytes */
  Elf64_Word    sh_link;                /* Link to another section */
  Elf64_Word    sh_info;                /* Additional section information */
  Elf64_Xword   sh_addralign;           /* Section alignment */
  Elf64_Xword   sh_entsize;             /* Entry size if section holds table */
} Elf64_Shdr;

由上述分析可知節(jié)頭部表(Section Header Table)的起始位置文件頭的偏移量為0x19d8字節(jié)钦睡。

輸入命令:

xxd hello

找到0x19d8即Section Header Table的起始點(diǎn)如下圖所示:

從起始點(diǎn)開始的Section Header Table的數(shù)據(jù)結(jié)構(gòu)如Elf64_Shdr結(jié)構(gòu)體所示。

通過輸入命令

readelf -S hello

可以查看Section Header Table躁倒,如下圖所示:

通過section header table找到各section

由前面的分析可知節(jié)頭部表(Section Header Table)中每一個(gè)表項(xiàng)的大小為64字節(jié)荞怒。

在第一節(jié)中,內(nèi)容全部為0不表示任何段秧秉。

在第二節(jié)中褐桌,為.interp段,段偏移sh_offset為0X238(紅線)象迎,段大小sh_size為0X1c(藍(lán)線)荧嵌。

在第三節(jié)中,為.note.ABI-tag節(jié)挖帘,節(jié)偏移sh_offset為0X 254(紅線)完丽,節(jié)大小sh_size為0X 20(藍(lán)線)。

第四個(gè)節(jié)拇舀,為.note.gnu.build-i段逻族,節(jié)偏移sh_offset為0X 274(紅線), 節(jié)大小sh_size為0X 24(藍(lán)線)骄崩。

第五個(gè)節(jié)聘鳞,為.gnu.hash節(jié),節(jié)偏移sh_offset為0X 298(紅線)要拂, 節(jié)大小sh_size為0X 1c(藍(lán)線)抠璃。

............中間節(jié)省略...........

第14節(jié).text節(jié)的表項(xiàng)起始地址=0x19d8+14*64=0x1d58

第14節(jié).text節(jié)的節(jié)偏移為0x430字節(jié),節(jié)大小為0x182字節(jié)脱惰。

其他節(jié)同理可推出搏嗡,其他節(jié)起始地址的表項(xiàng)起始地址=0x19d8+節(jié)序號(hào)*64。
然后通過相對(duì)文件頭的偏移地址和節(jié)大小可以找到各section拉一。

理解常見.text .strtab .symtab .rodata的section采盒。

1.text section是可執(zhí)行指令的集合,.data和.text都是屬于PROGBITS類型的section蔚润,這是將來要運(yùn)行的程序與代碼磅氨。

2.strtab section是屬于STRTAB類型的section,可以在文件中看到嫡纠,它存著字符串烦租,儲(chǔ)存著符號(hào)的名字延赌。

3.symtab section存放所有section中定義的符號(hào)名字,比如“data_items”叉橱,“start_loop”挫以。 .symtab section是屬于SYMTAB類型的section,它描述了.strtab中的符號(hào)在“內(nèi)存”中對(duì)應(yīng)的“內(nèi)存地址”赏迟。

4.rodata section屡贺,ro代表read only,即只讀數(shù)據(jù)(const)锌杀。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末甩栈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子糕再,更是在濱河造成了極大的恐慌量没,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件突想,死亡現(xiàn)場離奇詭異殴蹄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)猾担,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門袭灯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绑嘹,你說我怎么就攤上這事稽荧。” “怎么了工腋?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵姨丈,是天一觀的道長。 經(jīng)常有香客問我擅腰,道長蟋恬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任趁冈,我火速辦了婚禮歼争,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渗勘。我一直安慰自己矾飞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布呀邢。 她就那樣靜靜地躺著,像睡著了一般豹绪。 火紅的嫁衣襯著肌膚如雪价淌。 梳的紋絲不亂的頭發(fā)上申眼,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音蝉衣,去河邊找鬼括尸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛病毡,可吹牛的內(nèi)容都是我干的濒翻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼啦膜,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼有送!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起僧家,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤雀摘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后八拱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阵赠,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年肌稻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了清蚀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡爹谭,死狀恐怖枷邪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旦棉,我是刑警寧澤齿风,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站绑洛,受9級(jí)特大地震影響救斑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜真屯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一脸候、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绑蔫,春花似錦运沦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至篓叶,卻和暖如春烈掠,著一層夾襖步出監(jiān)牢的瞬間羞秤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工左敌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘾蛋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓矫限,卻偏偏與公主長得像哺哼,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叼风,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容