当前位置:文档之家› 加密解密:脱壳手记---Themida(2.1.2.0)

加密解密:脱壳手记---Themida(2.1.2.0)

加密解密:脱壳手记---Themida(2.1.2.0)
加密解密:脱壳手记---Themida(2.1.2.0)

加密解密:脱壳手记---Themida(2.1.2.0)

“衣带渐宽终不悔,为伊消得人憔悴”

------柳永《蝶恋花》

王国维先生曾以此比喻治学之第二境,我想以此与仍然苦苦挣扎在KSSD大教室的诸君共勉!

然则高版本的脱壳往往是建立在低版本之上,如果你对低版本已经有所了解可以忽略此处,如果需要了解可以看这里

https://www.doczj.com/doc/cf7957540.html,/showthread.php?t=172921 或移步KSSD

好了,进入正题!

上OD先直接F9跑一次。

程序结束后,将堆栈往上拉发现(图1):

有个返回到00401510,去反汇编窗口看看:

代码:

0040147E 8AD4 MOV DL,AH

00401480 8915 F4844000 MOV DWORD PTR DS:[4084F4],EDX

00401486 8BC8 MOV ECX,EAX

00401488 81E1 FF000000 AND ECX,0FF

0040148E 890D F0844000 MOV DWORD PTR DS:[4084F0],ECX

00401494 C1E1 08 SHL ECX,8

00401497 03CA ADD ECX,EDX

00401499 890D EC844000 MOV DWORD PTR DS:[4084EC],ECX

0040149F C1E8 10 SHR EAX,10

004014A2 A3 E8844000 MOV DWORD PTR DS:[4084E8],EAX

004014A7 6A 00 PUSH 0

004014A9 E8 A80A0000 CALL sayhello.00401F56

004014AE 59 POP ECX

004014AF 85C0 TEST EAX,EAX

004014B1 75 08 JNZ SHORT sayhello.004014BB

004014B3 6A 1C PUSH 1C

004014B5 E8 9A000000 CALL sayhello.00401554

004014BA 59 POP ECX

004014BB 8365 FC 00 AND DWORD PTR SS:[EBP-4],0 004014BF E8 72070000 CALL sayhello.00401C36 004014C4 E8 A0FA2E02 CALL 026F0F69

004014C9 90 NOP

004014CA A3 F8894000 MOV DWORD PTR DS:[4089F8],EAX 004014CF E8 30060000 CALL sayhello.00401B04 004014D4 A3 D0844000 MOV DWORD PTR DS:[4084D0],EAX 004014D9 E8 D9030000 CALL sayhello.004018B7 004014DE E8 1B030000 CALL sayhello.004017FE 004014E3 E8 90000000 CALL sayhello.00401578 004014E8 A1 04854000 MOV EAX,DWORD PTR DS:[408504] 004014ED A3 08854000 MOV DWORD PTR DS:[408508],EAX 004014F2 50 PUSH EAX

004014F3 FF35 FC844000 PUSH DWORD PTR DS:[4084FC] 004014F9 FF35 F8844000 PUSH DWORD PTR DS:[4084F8] 004014FF E8 FCFAFFFF CALL sayhello.00401000 00401504 83C4 0C ADD ESP,0C

00401507 8945 E4 MOV DWORD PTR SS:[EBP-1C],EAX 0040150A 50 PUSH EAX

0040150B E8 95000000 CALL sayhello.004015A5 00401510 8B45 EC MOV EAX,DWORD PTR SS:[EBP-14] 00401513 8B08 MOV ECX,DWORD PTR DS:[EAX] 00401515 8B09 MOV ECX,DWORD PTR DS:[ECX] 00401517 894D E0 MOV DWORD PTR SS:[EBP-20],ECX 0040151A 50 PUSH EAX

0040151B 51 PUSH ECX

0040151C E8 59010000 CALL sayhello.0040167A 00401521 59 POP ECX

00401522 59 POP ECX

00401523 C3 RETN

可以看出这是一段VC程序的伪OEP,头部被偷取了一些字节

进入CALL sayhello.00401000(图2)

和低版本一样,call都做了处理。

观察数据窗口,我们可以判断00405000为Iat段起始(图3):

好了,重新载入OD,在00405000下内存写入断点:

代码:

004487A0 8F02 POP DWORD PTR DS:[EDX] ;

断在004487A0(这里是VM代码)(图4)

看堆栈返回(图5)

发现调用代码为:

代码:

004C26F9 FF95 7A278906 CALL DWORD PTR SS:[EBP+689277A]

记得低版本的时候,它需要一张表,然后依据表中的数据分别取得原API地址,IAT地址和CALLAPI地址,这里是不是一样呢,我们在此处下个断点一看便知。

F9后我们查看[esi]发现了非常熟悉的一张表(图6):

找到了这里,我们知道它要取得各种地址就一定需要这里的数据。可以下内存访问断点后跟踪,也可以直接从004C26F9这个断点跟踪,都一样,因为它的处理过程必是一个循环的过程。

那么我们直接跟踪吧,先F8跳过这个CALL,暂时不去关心VM,先弄清楚流程。

很明显这个CALL之后,IAT填入了处理后的地址(图7)

同时,我们的[esi]表也变化了(图8):

可以看出至少获取callapi的步骤也是在VM里面完成了。继续单步,就快到下一个API的处理了,是的,就在这个”DDDDDDDD”之后。单步的过程便不详述,跟低版本相差无几,只不过增加了些垃圾代码。不一会便来到:

代码:

004BF68C C785 2D1D8206 0>MOV DWORD PTR SS:[EBP+6821D2D],0

004BF696 C785 311B8206 0>MOV DWORD PTR SS:[EBP+6821B31],0

004BF6A0 83BD 00B48C06 0>CMP DWORD PTR SS:[EBP+68CB400],0

非常熟悉的循环起始,和低版本一样,下面这段校验也需要修改:

代码:

004BF6E3 83BD 21158206 6>CMP DWORD PTR SS:[EBP+6821521],64

004BF6EA 0F82 09010000 JB sayhello.004BF7F9 ;这里修改成jmp跳过校验

以下一段判断[esi]表处理完毕:

代码:

004BF893 3D EEEEEEEE CMP EAX,EEEEEEEE

004BF898 0F85 AB000000 JNZ sayhello.004BF949

004BF89E F5 CMC

004BF89F 813E DDDDDDDD CMP DWORD PTR DS:[ESI],DDDDDDDD

004BF8A5 0F85 9E000000 JNZ sayhello.004BF949

004BF8AB F8 CLC

004BF8AC F8 CLC

004BF8AD 50 PUSH EAX

004BF8AE B8 00000000 MOV EAX,0

004BF8B3 8906 MOV DWORD PTR DS:[ESI],EAX

004BF8B5 8B0424 MOV EAX,DWORD PTR SS:[ESP]

004BF8B8 83C4 04 ADD ESP,4

004BF8BB E9 08000000 JMP sayhello.004BF8C8

004BF8C0 53 PUSH EBX

004BF8C1 F4 HLT ; 特权命令

004BF8C2 213D 7ADF2136 AND DWORD PTR DS:[3621DF7A],EDI

004BF8C8 52 PUSH EDX

004BF8C9 BA 04000000 MOV EDX,4

004BF8CE 81C6 5C04AE28 ADD ESI,28AE045C

004BF8D4 01D6 ADD ESI,EDX

004BF8D6 81EE 5C04AE28 SUB ESI,28AE045C

004BF8DC 5A POP EDX

004BF8DD E9 0F000000 JMP sayhello.004BF8F1

下面取得[esi]表的值:

代码:

004BF85C AD LODS DWORD PTR DS:[ESI]

继续跟踪到了一个循环:

代码:

004BFC57 3B02 CMP EAX,DWORD PTR DS:[EDX]

004BFC59 0F84 6F000000 JE sayhello.004BFCCE ;找到KEY跳出循环

004BFC5F 0F89 1E000000 JNS sayhello.004BFC83

004BFC65 60 PUSHAD

004BFC66 E8 14000000 CALL sayhello.004BFC7F

004BFC6B AB STOS DWORD PTR ES:[EDI]

004BFC6C F2: PREFIX

REPNE: ; 多余前缀

004BFC6D 93 XCHG EAX,EBX

004BFC6E 6B30 A8 IMUL ESI,DWORD PTR DS:[EAX],-58

004BFC71 B6 FD MOV DH,0FD

004BFC73 D19E 2B586176 RCR DWORD PTR DS:[ESI+7661582B],1

004BFC79 B7 07 MOV BH,7

004BFC7B 05 CCF02A5A ADD EAX,5A2AF0CC

004BFC80 60 PUSHAD

004BFC81 61 POPAD

004BFC82 61 POPAD

004BFC83 57 PUSH EDI

004BFC84 893424 MOV DWORD PTR SS:[ESP],ESI

004BFC87 BE 04000000 MOV ESI,4

004BFC8C 01F2 ADD EDX,ESI

004BFC8E 5E POP ESI

004BFC8F FC CLD

004BFC90 52 PUSH EDX

004BFC91 BA 01000000 MOV EDX,1

004BFC96 01D1 ADD ECX,EDX

004BFC98 5A POP EDX

004BFC99 F9 STC

004BFC9A 3B8D B8BF8B06 CMP ECX,DWORD PTR SS:[EBP+68BBFB8]

004BFCA0 ^ 0F85 B1FFFFFF JNZ sayhello.004BFC57

根据低版本的流程,这里是要获取一个偏移值,每个API对应不同的偏移,

这张偏移表可以看做存的是对应API的解密KEY由TMD维护,跟我们脱壳关系不大,我们在004BFCCE下硬件执行断点跳过循环

代码:

004BFCCE 898D E11C8206 MOV DWORD PTR SS:[EBP+6821CE1],ECX

在这行代码后出现了原始api地址:

代码:

004BFED7 01C8 ADD EAX,ECX

004BFED9 2D 190F5568 SUB EAX,68550F19

有的模块的api在此处还只是一个字符串,继续单步一会:

代码:

004C026C 61 POPAD

004C026D FFD3 CALL EBX ;经过这个CALL后得到API原始地址

004C026F 60 PUSHAD ;此时eax为API地址

取得API地址后,它会对API进行处理,处理过程会放在VM中,但是也有一些函数不做处理,那么它将有一个判断,我们继续单步寻找这个判断(单步中会经历一个TMD在自己申请的地址重新构造API的过程,和低版本思路一样,这里就不详述了)。经历漫长的单步后来到下面(当然,直接在开始的返回后向上找很快就会找到,当然顺序下来有利于我们对流程的了解)

代码:

004C26DF 83BD E9B48C06 0>CMP DWORD PTR SS:[EBP+68CB4E9],0

004C26E6 0F85 91000000 JNZ sayhello.004C277D

这个时候我们还没有发现IAT的地址,可见它也在是VM中处理的。

到VM这里的流程清楚了,我们先直接看看不加密的情况,

004C26DF处下断点,断不加密条件我们开始单步:

代码:

004C279A 0385 AD108206 ADD EAX,DWORD PTR SS:[EBP+68210AD] ;eax为IAT 地址

004C27A0 F5 CMC

然后是对CALLAPI地址的处理,和低版本一样,有对”90”填充的处理,我们都可以不管,因为我们将对CALLAPI重新填充:

004C291C 0385 AD108206 ADD EAX,DWORD PTR SS:[EBP+68210AD] ;这里[EAX]callapi地址

004C2922 F9 STC

004C2923 83BD F9148206 0>CMP DWORD PTR SS:[EBP+68214F9],1

004C292A 0F84 F1040000 JE sayhello.004C2E21

004C293E 61 POPAD ;这里[EAX]是CALLAPI地址

004C293F 813E AAAAAAAA CMP DWORD PTR DS:[ESI],AAAAAAAA ;比较是否填充FF25

---------------------------------------------------------------------------------------------------------------------------------

004C293F 也是我们需要的一个断点

代码:

004C2DF4 AB STOS DWORD PTR ES:[EDI] ;这里CALLAPI处理完毕,可以重新写回去

004C2DF5 60 PUSHAD

通过以上的步骤,整个流程我们就清楚了,我们下面就来看看VM吧。所谓VM我理解的是它将原本的指令作了新的约定,并按照新的约定执行变形的代码来替换或者说”等价”的完成原先的指令集,它的每一个新约定指令都有一个指令序列来实现。稍微跟踪一下,可以发现以下两条重要的代码

代码:

00442221 AC LODS BYTE PTR DS:[ESI] ;这里取得一个VM字节,将通过对这个字节进行计算,获取指令序列的跳转

00442222 30D8 XOR AL,BL

代码:

00447B00 /FF2487 JMP DWORD PTR DS:[EDI+EAX*4] ; 跳转到指令序列00447B03 |61 POPAD

00447B04 |C3 RETN

跟到[edi]发现一个指令序列表(图9):

当然要仔细分析的话,可以记录以上两个断点比较。当然我们现在不去分析它,我们主要是为了脱壳。

跟踪发现几个关键数据写入都通过

004487A0 8F02 POP DWORD PTR DS:[EDX] ;

通过打印脚本分析004487a0,记录[esp]和edx(因为它们将出现关键数据,这个再跟踪过程中可以发现,TMD差不多都这样,当然不同的VM引擎是可以设置不一样的,具体可以移步KSSD-->保护篇-->虚拟机)

跟踪脚本:

代码:

var vedx

var vesp

var x

bphwc

bphws 004487a0 ,"x"

bphws 004c0169,"x"

mov x,0

esto

loop:

cmp eip,004487a0

jne exit

mov vedx,edx

mov vesp,[esp]

inc x

log x

log vedx

log vesp

cmp x,15

je exit

esto

jmp loop

exit:

ret

通过观察记录得到以下数据:

第0a次出现混淆后的API地址

第016次计算出iat的RVA

第017次计算出iat的VA

第019次填充iat

第0x1f次计算出callapi地址

第0x25次填充callpi偏移,填充e8 e9的代码不在此处须另外寻找

第0x26次比较esi的下一个元素看是否为ffffffff,如果不是则证明还有需要填充的callapi

如果为ffffffff则将在第0x28次之后进入下一个循环

如果不为ffffffff则将在第0x2b处计算出下一个callapi地址

同样6次断之后在第0x31次填充callapi地址

好了下面分析计算iat的代码在第0x16次后下断点:

代码:

00444DB0 311C24 XOR DWORD PTR SS:[ESP],EBX

00444DB3 331C24 XOR EBX,DWORD PTR SS:[ESP]

00444DB6 8B2424 MOV ESP,DWORD PTR SS:[ESP]

00444DB9 010424 ADD DWORD PTR SS:[ESP],EAX ; sayhello.00400000

经过跟踪发现00444DB9处代码计算出iat地址,此时iat地址存放在[esp]处

然后继续分析callapi偏移

在第0x1e次后下断点跟踪:

发现写入callapi的地址也是在00444DB9处

可以在虚拟机段找这段特征码(不过不必过于相信特征码,版本不同会略有差异,但方法都是一样的)

下面继续分析比较ffffffff在第0x26次断点后分析结果跟踪到此处:

比较ecx 和eax ,相等则元素结束了不相等证明还有callapi

代码:

0044D099 8B2424 MOV ESP,DWORD PTR SS:[ESP]

0044D09C 3BC8 CMP ECX,EAX

下断点00444DB9 加硬件断点004C026F测试一下

发现00444DB9此处需要判断条件eax==00400000时才得到IAT或者CALLAPI地址,且第一次是IAT地址(其实就这一个断点已经可以处理VM的IAT地址,第一个是IAT,后面都是callapi地址)

0044D09C 也要条件 eax==ffffffff eax!=ffffffff则证明还有未处理的CALLAPI ,如果相等则证明当前API元素已处理完。

有了以上的条件,我们就可以写脚本来完成脱壳了。

这样整理一下主要断点:

004C026F ----------取得API原始地址

Case1:

004C26F9 ---------这里进入VM,部分函数的IAT和CALLAPI获取填充都在这里实现

Case2:

004C27A0 --------这里断下来则是不需要加密的API的IAT,值在eax中

--------用来做判断之后需要增加一个辅助断点取IAT,单步几行代码找到

004c27ce

Case_VM:

00444DB9 ---------这里断下后通过判断eax==00400000,外加一个数字标识来区分取得的IAT还是callapi

等待执行完毕直接填充正确IAT和FF15call

Case_NOTVM:

004C293F ---------------------这里取得callapi值

004C2DF5 --------------这里填充完毕,重新写回去

代码:

var api

var iat

var callapi

var n

bc

bphwc

bphws 004c026f,"x" ;取得原始API地址

esto

bp 004BF8DD ;处理完毕,可以调到OEP,当然也可以不要这个断点,因为OEP在前面可以通过退出法已经找到了

bp 004C26F9 ;进入VM

bp 00444DB9 ;VM中得到IAT和CALLAPI地址

bp 004C27A0 ;不加密的IAT

bp 004C293F ;不加密的CALLAPI

bp 004C2DF5 ;CALLAPI填充完毕,重新写回

bp 004c27ce ;因为004C27A0作为了是否加密的跳转条件,因此在下面增加一个断点来取不加密的IAT

mov [004bf6ea],#E90A01000090# ;校验处改为JMP略过

loop:

cmp eip,004c026f

jne swtich

mov api,eax

mov n,0 ;判断VM中的IAT和CALLAPI

esto

jmp loop

swtich: ;分别加密处理的和不加密处理的

cmp eip,004C27A0

je notvm

cmp eip,004C26F9

je vm

jmp exit

notvm:

cmp eip,004C27A0

jne filliat

mov iat,eax

esto

jmp notvm

filliat:

cmp eip,004C27CE

jne callapi

mov [iat],api ;得到IAT,有些加密API也在这里处理IAT esto

jmp notvm

callapi:

cmp eip,004C293F

jne fillcallapi

mov callapi,eax ;得到CALLAPI地址

esto

jmp notvm

fillcallapi:

cmp eip,004C2DF5

jne loop

find callapi,#E9#,2 ;比较是否填充FF25

cmp $RESULT,0

jne fillFF25A

mov [callapi],#ff15#

add callapi,2

mov [callapi],iat

esto

jmp notvm

fillFF25A:

mov [callapi],#ff25#

add callapi,2

mov [callapi],iat

esto

jmp notvm

vm:

esto

cmp eip,00444DB9

jne loop

cmp eax,00400000 ;条件eax==00400000时才可能是ITA或者CALLAPI jne vm

inc n

cmp n,1 ;n来判断当前是处理IAT还是处理CALLAPI jne callapifun

mov iat,[esp]

add iat,00400000 ;得到IAT或者CALLAPI的VA

bp 004487a0 ;新增断点,此处的代码将填充IAT

esto

esto

esto

esto

mov [iat],api ;四次F9后IAT填充完毕

BC 004487a0

jmp vm

callapifun:

mov callapi,[esp]

add callapi,00400000

bp 004487a0 ;新增断点,此处的代码将填充CALLAPI

esto

esto

esto

esto

esto

esto

esto

esto

esto

esto ;十次F9后CALLAPI填充完毕

find callapi,#E9#,2 ;比较是否填充FF25

cmp $RESULT,0

bc 004487a0

jne fillFF25b

mov [callapi],#ff15#

add callapi,2

mov [callapi],iat

jmp vm

fillFF25b:

mov [callapi],#ff25#

add callapi,2

mov [callapi],iat

jmp vm

exit:

bc

bphwc

bprm 00401000,4000 ;处理完毕后下内存访问断点,将断在OEP

esto

ret

后面按照常规方法恢复OEP即可,和低版本一样。TMD版本会有所不同,加壳方式也会略有差异,

但总体流程都是这样,按照这个思路去分析,大体脱壳是没有问题的!

(完整版)常见几种脱壳方法

----------------<小A分>---------------- 一、概论 壳出于程序作者想对程序资源压缩、注册保护的目的,把壳分为压缩壳和加密壳(强壳)两种 "UPX" "ASPCAK" "TELOCK" "PELITE" "NSPACK(北斗)" ... "ARMADILLO" "ASPROTECT" "ACPROTECT" "EPE(王)" "SVKP" ... 顾名思义,压缩壳只是为了减小程序体积对资源进行压缩,加密壳是程序输入表等等进行加密保护。 当然加密壳的保护能力要强得多! -----------<小A分割线>------------- 二、工具的认识 OllyDBG ring3 shell层级别的动态编译工具、 PEid、 ImportREC、 LordPE、 softIce ring0级别调试工具 -------------<小A分割>------------------- 三、常见手动脱壳方法 预备知识 1.PUSHAD (入栈/压栈)代表程序的入口点, 2.POPAD (弹栈/出栈)代表程序的出口点,与PUSHAD想对应,一般找到这个OEP就在附近 3.OEP:程序的入口点,软件加壳就是隐藏了OEP(或者用了假的OEP/FOEP),只要我们找到程序真正的OEP,就可以立刻脱壳。 ------------<小A分割线>-------------------- 方法一:单步跟踪法 1.用OD载入,点“不分析代码!” 2.单步向下跟踪F8,实现向下的跳。也就是说向上的跳不让其实现!(通过F4) 3.遇到程序往回跳的(包括循环),我们在下一句代码处按F4(或者右健单击代码,选择断点——>运行到所选) 4.绿色线条表示跳转没实现,不用理会,红色线条表示跳转已经实现! 5.如果刚载入程序,在附近就有一个CALL的,我们就F7跟进去,不然程序很容易跑飞,这样很快就能到程序的OEP 6.在跟踪的时候,如果运行到某个CALL程序就运行的,就在这个CALL中F7进入 7.一般有很大的跳转(大跨段),比如 jmp XXXXXX 或者 JE XXXXXX 或者有RETN 的一般很快就会到程序的OEP。 近CALL F7 远CALL F8 Btw:在有些壳无法向下跟踪的时候,我们可以在附近找到没有实现的大跳转,右键-->“跟随”,然后F2下断,Shift+F9运行停在“跟随”的位置,再取消断点,

怎样使用脱壳软件

第二节脱壳 一切从“壳”开始 吴朝相1999.2.23 (搜新网https://www.doczj.com/doc/cf7957540.html,) 我写这篇东西的主要目的是让初到本站的新手们能对“壳”有个大概的认识,知道我每天说了些什么。限于本人的知识,如果有ERROR 之处,还请多原谅。如果你觉得还可以,也欢迎转贴,但请保留文章的完整性和作者的资料。当然如果你想把它发表,硬塞些稿费给俺花花,我也不会拒绝的。;) 作为一个以“壳”为主的站台,如果连访者连什么是“壳”都不清楚的话,那我也太失败了。很早以前就想写编完全关于“壳”的文章,但苦于时间和文字水平的关系,都没提笔。本着对站台负责的态度,现在经过一天的努力,“打”出这编尝试由壳的历史一直谈到最新发展的本章来。 首先我想大家应该先明白“壳”的概念。在自然界中,我想大家对壳这东西应该都不会陌生了,植物用它来保护种子,动物用它来保护身体等等。同样,在一些计算机软件里也有一段专门负责保护软件不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。就像动植物的壳一般都是在身体外面一样理所当然(但后来也出现了所谓的“壳中带籽”的壳)。由于这段程序和自然界的壳在功能上有很多相同的地方,基于命名的规则,大家就把这样的程序称为“壳”了。就像计算机病毒和自然界的病毒一样,其实都是命名上的方法罢了。 最早提出“壳”这个概念的,据我所知,应该是当年推出脱壳软件RCOPY 3 的作者熊焰先生。在几年前的DOS 时代,“壳”一般都是指磁盘加密软件的段加密程序,可能是那时侯的加密软件还刚起步不久吧,所以大多数的加密软件(加壳软件)所生成的“成品”在“壳”和需要加密的程序之间总有一条比较明显的“分界线”。有经验的人可以在跟踪软件的运行以后找出这条分界线来,至于这样有什么用这个问题,就不用我多说了。但毕竟在当时,甚至现在这样的人也不是很多,所以当RCOPY3 这个可以很容易就找出“分界线”,并可以方便的去掉“壳”的软件推出以后,立即就受到了很多人的注意。老实说,这个我当年在《电脑》杂志看到广告,在广州电脑城看到标着999元的软件,在当时来说,的确是有很多全新的构思,单内存生成EXE 可执行文件这项,就应该是世界首创了。但它的思路在程序的表现上我认为还有很多可以改进的地方(虽然后来出现了可以加强其功力的RO97),这个想法也在后来和作者的面谈中得到了证实。在这以后,同类型的软件想雨后春笋一般冒出来,记得住名字的就有:UNKEY、MSCOPY、UNALL .... 等等,但很多的软件都把磁盘解密当成了主攻方向,忽略了其它方面,当然这也为以后的“密界克星”“解密机器”等软件打下了基础,这另外的分支就不多祥谈了,相信机龄大一点的朋友都应该看过当时的广告了。 解密(脱壳)技术的进步促进、推动了当时的加密(加壳)技术的发展。LOCK95和BITLOK 等所谓的“壳中带籽”加密程序纷纷出笼,真是各出奇谋,把小小的软盘也折腾的够辛苦的了。正在国内的加壳软件和脱壳软件较量得正火红的时候,国外的“壳”类软件早已经发展到像LZEXE 之类的压缩壳了。这类软件说穿了其实就是一个标准的加壳软件,它把EXE 文件压缩了以后,再在文件上加上一层在软件被执行的时候自动把文件解压缩的“壳”来达到压缩EXE 文件的目的。接着,这类软件也越来越多,PKEXE、AINEXE、UCEXE 和后来被很多人认识的WWPACK 都属于这类软件,但奇怪的是,当时我看不到一个国产的同类软件。 过了一段时间,可能是国外淘汰了磁盘加密转向使用软件序列号的加密方法吧,保护EXE 文件不被动态跟踪和静态反编译就显得非常重要了。所以专门实现这样功能的加壳程序便诞生了。MESS 、

网络安全常见的四种加密解密算法

package mima; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Scanner; public class Mainer { StringBuffer MStr = new StringBuffer(""); // 加密字符串 StringBuffer CStr = new StringBuffer(""); // 解密字符串 public static void main(String[] args) { System.out.print("请输入密钥:"); Scanner s = new Scanner(System.in); int key = s.nextInt() % 26; // %26的意义是获取密钥的偏移值 Mainer ks = new Mainer(); ks.E(key); // 加密 ks.D(key); // 解密 } /** * 加密公式 */ void E(int k) { try { System.out.println("请输入一段明文:"); char b[]; BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in)); String str2 = br2.readLine(); b = str2.toCharArray(); char ch = ' '; for (int i = 0; i < str2.length(); i++) { if (b[i] >= 'a' && b[i] <= 'z') { ch = (char) ((b[i] - 'a' + k) % 26 + 'a'); } if(b[i] >= 'A' && b[i] <= 'Z'){ ch = (char) ((b[i] - 'A' + k) % 26 + 'A'); } if(b[i]>='0'&&b[i]<='9')

四种加密解密算法的源代码:移位密码、仿射密码

四种加密解密算法的源代码:移位密码、仿射密码、维吉尼亚密码以及置换密码#include #include #include #include void Shift() /*移位密码*/ { char c[100]; int length, i=0, key=0; clrscr(); printf("********Shift Cipher********\nPlease input primal sentence: "); gets(c); length = strlen(c); printf("Input the key(0~26): "); scanf("%d", &key); getchar(); if(key<0) { printf("The value of key is error!\nPress any key to return..."); getch(); return; } for(i=0; i96&&c[i]<123) c[i] = (c[i]+key-97)%26+65; else if(c[i]>64&&c[i]<91) c[i] = (c[i]+key-65)%26+65; } printf("Result is: %s\n", c); for(i=0; i64&&c[i]<91) c[i] = (c[i]-key-65+26)%26+97; } printf("\nAfter translated the sentence,we can see the primal sentence as follow:\n%s\n", c); printf("Press any key to return..."); getch(); }

加壳与脱壳应用及实现

加壳与脱壳的应用与实现

一、加壳 (2) 1.什么是壳 (2) 2.加壳原因 (2) 3.壳的加载过程 (3) 4.压缩引擎 (5) 5.常见的加壳工具 (6) a.常用压缩壳介绍 (6) b.加密保护壳介绍 (7) 二、脱壳 (10) 1.侦壳 (10) 2.脱壳 (13) a.查找程序的真正入口点(OEP) (13) b.抓取内存映像文件 (15) c.输入表重建 (15) 附:视频“加壳与脱壳(软件)”和“手动脱壳” (17)

加壳与脱壳 一、加壳 1.什么是壳 在一些计算机软件里也有一段专门负责保护软件不被非法修改或反编译的程序。它们一般都是先于程序运行,拿到控制权,然后完成它们保护软件的任务。由于这段程序和自然界的壳在功能上有很多相同的地方,基于命名的规则,就把这样的程序称为“壳”了。 图1.1 2.加壳原因 就把这样的程序称为“壳”了。 作者编好软件后,编译成exe可执行文件。 1)有一些版权信息需要保护起来,不想让别人随便改动,如作者

的姓名,即为了保护软件不被破解,通常都是采用加壳来进行保护。 2)需要把程序搞的小一点,从而方便使用。于是,需要用到一些软件,它们能将exe可执行文件压缩。 3)在黑客界给木马等软件加壳脱壳以躲避杀毒软件。实现上述功能,这些软件称为加壳软件。 3.壳的加载过程 1)获取壳自己所需要使用的API地址 如果用PE编辑工具查看加壳后的文件,会发现未加壳的文件和加壳后的文件的输入表不一样,加壳后的输入表一般所引入的DLL和API函数很少,甚至只有Kernel32.dll以及GetProcAddress这个API 函数。 壳实际上还需要其他的API函数来完成它的工作,为了隐藏这些API,它一般只在壳的代码中用显式链接方式动态加载这些API函数2)解密原程序的各个区块(Section)的数据 壳出于保护原程序代码和数据的目的,一般都会加密原程序文件的各个区块。在程序执行时外壳将会对这些区块数据解密,以让程序能正常运行。壳一般按区块加密的,那么在解密时也按区块解密,并且把解密的区块数据按照区块的定义放在合适的内存位置。 如果加壳时用到了压缩技术,那么在解密之前还有一道工序,当然是解压缩。这也是一些壳的特色之一,比如说原来的程序文件未加壳时1~2M大小,加壳后反而只有几百K。

实验四RSA加解密算法的实现

实验四 RSA加解密算法的实现 一.实验目的 1、对算法描述可进行充分理解,精确理解算法的各个步骤。 2、完成RSA软件算法的详细设计。 3、用C++完成算法的设计模块。 4、编制测试代码。 二.实验内容 1.实验原理及基本技术路线图(方框原理图) 加密过程: 第一步,用户首先输入两个素数p和q,并求出 n = p*q,然后再求出n的欧拉函数值phi。 第二步,在[e,phi]中选出一个与phi互素的整数e,并根据e*d ≡1(mod phi),求出e的乘法逆元。至此我们已经得到了公开密钥{e,n}和秘密密钥{d,n}。 第三步,让用户输入要进行加密的小于n一组正整数(个数不超过MAXLENGTH=500),输入以-1为结束标志,实际个数存入size中,正整数以clear[MAXLENGTH]保存。 第四步,对第三步所得的明文clear[MAXLENGTH]进行加密。遍历clear[size],对每一个整数用以下算法进行加密,并将加密后的密文保存在Ciphertext[MAXLENGTH]中。 注意:此处不能用m2[j] = clear[j] ^ e整数的幂,因为当e和clear[j]较大时,会发生溢出,至使出现无法预料的结果。 第五步,输出加密后的密文。 解密过程: 第一步,根据在以上算法中求出的解密密钥[d,phi],对加密后的密文Ciphertext[MAXLENGTH]进行解密,结果保存在DecryptionText[MAXLENGTH]中,算法如下: 第二步,输出对加密前的明文和加密并解密后的密文进行比较,判断两个数组是否一致,从而得知算法是否正确。

2.所用仪器、材料(设备名称、型号、规格等) 计算机一台、vc6.0 3.实验方法、步骤 #include #include using namespace std; #define MAXLENGTH 500 //明文最大长度,即所允许最大整数个数 int size = 0;//保存要进行加密的正整数的个数 int p, q; //两个大素数 int n, phi; //n = p * q,phi = (p-1) * (q-1) 是n的欧拉函数值 int e; //{e, n}为公开密钥 int d; //{d, n}为秘密密钥 int clear[MAXLENGTH], Ciphertext[MAXLENGTH];//分别用于存放加//密前的明//文和加密后的密文int DecryptionText[MAXLENGTH];//存放解密后的明文 //////////////////////////////////////////////////////////// //以下为加密算法 void Encryption() {//加密算法 cout << " 请输入两个较大的素数:" ; cin >> p >> q ; cout << " p = " << p << ", q = " << q << endl; n = p * q;//求解 n, phi = (p - 1) * ( q - 1 );//求解 n 的欧拉函数值 cout << " n = " << n << ", phi = " << phi << endl; cout << " 请从[0," << phi - 1 << "]中选择一个与 " << phi << " 互素的数 e:"; cin >> e; float d0; for( int i = 1; ; i++) {///求解乘法逆元 e * d ≡ 1 (mod phi) d0 = (float)(phi*i+1) / e; if( d0 - (int)d0 == 0 ) break; } d = (int)d0; cout << endl; cout << " e = " << e << ", d = " << d << endl; cout << " 公开密钥 Pk = {e,n} = {" << e << "," << n << "}" << endl; cout << " 秘密密钥 Sk = {d,n} = {" << d << "," << n << "}" << endl; cout << endl;

RSA加密解密的设计与实现

RSA加密解密的设计与实现

上海电力学院 《应用密码学》课程设计 题目: RSA加密解密的设计与实现 院系:计算机科学与技术学院 专业年级:级 学生姓名:李正熹学号: 3273 指导教师:田秀霞 1月 8日 目录

目录 1.设计要求 2.开发环境与工具 3.设计原理(算法工作原理) 4.系统功能描述与软件模块划分 5.设计核心代码 6.参考文献 7. 设计结果及验证 8. 软件使用说明 9. 设计体会 附录 1.设计要求

1 随机搜索大素数,随机生成公钥和私钥 2 用公钥对任意长度的明文加密 3 用私钥对密文解密 4 界面简洁、交互操作性强 2.开发环境与工具 Windows XP操作系统 Microsoft Visual C++ 6.0 1.创立rsa工程

2.在rsa工程中创立 3273 李正熹cpp文件 3.设计原理 RSA算法简介 公开密码算法与其它密码学完全不同,它是基于数学函数而不是基于替换或置换。与使用一个密钥的对称算法不同,公开密钥算法是非对称的,而且它使用的是两个密钥,包括用于加密的公钥和用于解密的私钥。公开密钥算法有RSA、Elgamal等。 RSA公钥密码算法是由美国麻省理工学院(MIT)的Rivest,Shamir和Adleman在1978年提出来的,并以她们的名字的有字母命名的。RSA是第一个安全、实用的公钥密码算法,已经成为公钥密码的国际标准,是当前应用广泛的公钥密码体制。

RSA的基础是数论的Euler定理,其安全性基于二大整数因子分解问题的困难性,公私钥是一对大素数的函数。而且该算法已经经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这不恰恰说明该算法有其一定的可信度。 4.系统功能描述与软件模块划分 功能:

PE文件中脱壳技术的研究

第27卷第9期 计算机应用与软件 Vol 127No .92010年9月 Computer App licati ons and Soft w are Sep.2010 PE 文件中脱壳技术的研究 李 露 刘秋菊 徐汀荣 (苏州大学计算机科学与技术学院 江苏苏州215006) 收稿日期:2009-01-07。李露,硕士生,主研领域:网络安全,信息技术。 摘 要 对PE (Portable Executable )文件进行加壳是保护软件的有效手段,但恶意程序也会通过加壳来保护自己。作为一名病毒 分析师或软件安全分析员,只有先将其脱壳,才能进行彻底的分析。以W indows 记事本程序为实例,首先分析了PE 文件结构及其加壳原理,其次阐述了脱壳的一般步骤,然后从压缩壳和加密壳的角度,重点探讨了脱壳技术的原理和方法。最后对伪装壳和多重壳及程序自校验进行了探讨和分析。 关键词 PE 加壳 脱壳 伪装壳 多重壳 自校验 O N UNPACK I NG TECHNOLO GY FO R PE F I L ES L i Lu L iu Q iuju Xu Tingr ong (School of Co m puter Science and Technology,Soocho w U niversity,Suzhou 215006,J iangsu,China ) Abstract Packing Portable Executable (PE )files is an effective mean t o p r otect s oft w are,but mal w are can als o use packing t o p r otect the m selves .A s a virus analyst or a s oft w are security researcher,you must unpack the mal w are first,then can you analysis the m in detail .Taking the notepad p r ogra m in M icr os oftW indows as an in this paper we first analyzed the PE file structure and the p rinci p le of packing,and then expounded the general step s of unpacking .After that,in ter m s of the comp ressi on shell and encryp ti on shell,we f ocused on the p rinci p les and methods of unpacking technol ogy .Finally,we discussed and analyzed the ca mouflage shell,multi 2shell and self 2chec 2king . Keywords PE Packing Unpacking Ca mouflage shell Multi 2shell Self 2checking 0 引 言 PE 文件格式是W I N 32环境自带的跨平台可执行文件格 式,常见的EXE 、DLL 、OCX 、SYS 、COM 等文件均是PE 格式。使用该格式,在非I ntel 芯片的CP U 上,W indows 一样能识别和使用。 对PE 文件加壳,能较好地保护原程序。但病毒和木马也会利用加壳技术来保护自己,因为加壳后程序执行结果不变,但代码发生了变化,从而使杀毒软件无法查杀。作为一名病毒分析师或者软件安全研究员,如果不懂得脱壳技术,将很难对这些恶意程序进行分析。据瑞星公司截获的病毒样本统计,90%以上的病毒文件都经过加壳处理,可见掌握脱壳技术十分重要。现有文章大都进行加壳技术的探讨[1-3],本文则着重研究脱壳技术。 1 壳的介绍 壳是一段附加在原程序上的代码,它先于真正的程序运行并拿到控制权,在完成程序保护任务后(检测程序是否被修改,是否被跟踪等),再将控制权转交给真正的程序,其运行过程与病毒有些相似。在形式上又与W I N RAR 类的压缩软件类似,运行前都需要将原程序解压。但壳对程序的解压是在内存中进行,对用户来说完全透明,用户感觉不到壳的存在。 壳分为压缩壳和加密壳。压缩壳只是为了减少程序体积而 对资源进行压缩,便于传输,具有一定的保护作用。常见的压缩壳有UPX 、ASPCAK 、TE LOCK 、PE L I TE 、NSP ACK 等。加密壳是使用各种手段对程序资源进行保护,防止其被反汇编或跟踪,文件加壳后是否变小不是其主要目标。常见的加密壳有AR MA 2D I L LO 、ASPROTECT 、ACPROTECT 、EPE 、S VKP 等。目前一些壳已兼具有两种功能,即能压缩资源,又能加密资源。 2 PE 结构框架 PE 文件使用一个平面地址空间,所有代码和数据都被合并 成一个很大的结构。文件内容由属性相同的区块组成,各区块按页边界对齐,大小没有限制。每个区块都有不同的名字,用来表示区块的功能。图1是W indows98下记事本Notepad .exe 程序的PE 结构图。从图中可以看出PE 文件由几个连续的区块组成。先后由DOS 头部、PE 头部、区段表以及各个区段组成。其中.text 是代码段,.data 是已初始化的数据段,.idata 是输入表段,.rsrc 是资源段,.rel oc 是基址重定位表段 。 图1 W indows98记事本PE 结构图

RSA加密算法加密与解密过程解析

RSA加密算法加密与解密过程解析 1.加密算法概述 加密算法根据内容是否可以还原分为可逆加密和非可逆加密。 可逆加密根据其加密解密是否使用的同一个密钥而可以分为对称加密和非对称加密。 所谓对称加密即是指在加密和解密时使用的是同一个密钥:举个简单的例子,对一个字符串C做简单的加密处理,对于每个字符都和A做异或,形成密文S。 解密的时候再用密文S和密钥A做异或,还原为原来的字符串C。这种加密方式有一个很大的缺点就是不安全,因为一旦加密用的密钥泄露了之后,就可以用这个密钥破解其他所有的密文。 非对称加密在加密和解密过程中使用不同的密钥,即公钥和私钥。公钥用于加密,所有人都可见,私钥用于解密,只有解密者持有。就算在一次加密过程中原文和密文发生泄漏,破解者在知道原文、密文和公钥的情况下无法推理出私钥,很大程度上保证了数据的安全性。 此处,我们介绍一种非常具有代表性的非对称加密算法,RSA加密算法。RSA 算法是1977年发明的,全称是RSA Public Key System,这个Public Key 就是指的公共密钥。 2.密钥的计算获取过程 密钥的计算过程为:首先选择两个质数p和q,令n=p*q。 令k=?(n)=(p?1)(q?1),原理见4的分析 选择任意整数d,保证其与k互质 取整数e,使得[de]k=[1]k。也就是说de=kt+1,t为某一整数。

3.RSA加密算法的使用过程 同样以一个字符串来进行举例,例如要对字符串the art of programming 进行加密,RSA算法会提供两个公钥e和n,其值为两个正整数,解密方持有一个私钥d,然后开始加密解密过程过程。 1. 首先根据一定的规整将字符串转换为正整数z,例如对应为0到36,转化后形成了一个整数序列。 2. 对于每个字符对应的正整数映射值z,计算其加密值M=(N^e)%n. 其中N^e表示N的e次方。 3. 解密方收到密文后开始解密,计算解密后的值为(M^d)%n,可在此得到正整数z。 4. 根据开始设定的公共转化规则,即可将z转化为对应的字符,获得明文。 4.RSA加密算法原理解析 下面分析其内在的数学原理,说到RSA加密算法就不得不说到欧拉定理。 欧拉定理(Euler’s theorem)是欧拉在证明费马小定理的过程中,发现的一个适用性更广的定理。 首先定义一个函数,叫做欧拉Phi函数,即?(n),其中,n是一个正整数。?(n)=总数(从1到n?1,与n互质整数) 比如5,那么1,2,3,4,都与5互质。与5互质的数有4个。?(5)=4再比如6,与1,5互质,与2,3,4并不互质。因此,?(6)=2

DES加密算法与解密(带流程图)

一、DES加密及解密算法程序源代码: #include using namespace std; const static char IP_Table[] = { //IP_T able置换58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 }; const static char Final_Table[] = { //最终置换40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26,

33, 1, 41, 9, 49, 17, 57, 25 }; const static char S_Box[8][64] = { //s_box /* S1 */ {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}, /* S2 */ {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}, /* S3 */ {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}, /* S4 */ {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,

13 脱壳技术

任何事物都有两面性,有加壳,就必有脱壳。加壳与脱壳有着紧密的联系,一些脱壳技术是针对加壳而产生的,脱壳的进步,又迫使加壳软件不断创新发展。现在越来越多的软件都加壳保护,脱壳有时是分析一个软件不可缺少的步骤。 ……略…… 13.5 DLL 文件脱壳 DLL 是Dynamic Link Library (动态链接库)的缩写形式,是一个共享函数库的可执行文件。DLL 文件的脱壳与EXE 文件步骤差不多,DLL 文件多了个基址重定位表等要考虑。 13.5.1 寻找OEP 当DLL 被初次映射到进程的地址空间中时,系统将调用DllMain 函数,当卸载DLL 时也会再次调用DllMain 函数。也就是说,DLL 文件相比EXE 文件运行有一些特殊性,EXE 的入口点只在开始时执行一次,而DLL 的入口点在整个执行过程中至少要执行两次。一次是在开始时,用来对DLL 做一些初始化。至少还有一次是在退出时,用来清理DLL 再退出。 外壳编写时也必须考虑这个因素,初次载入时,做些初始化工作,如IAT 初始化等。退出时再次进入入口点时,外壳将跳过相关的初始化代码,这时程序代码流程会短些。所以找OEP 也有两条路可以走,一是载入时找,二是在退出时找,退出时流程短些,相对来说更容易找到OEP 。 用第16章编写的加壳工具对实例EdrLib.dll 进行加壳处理。用LordPE 查看其PE 信息,获得EntryPoint 为D000h ,ImageBase 为400000h ,区块的信息如图13.41所示。 图13.41 查看区块信息 DLL 本身不能直接执行,但可以调用LoadLibrary 将DLL 的文件映像映射到调用进程的地址空间中,退出时调用FreeLibrary 卸载DLL 。为了调试DLL ,OllyDbg 提供了一个类似原理的辅助程序loaddll.exe ,这个程序被压缩存放在资源段里,如果OllyDbg 所在文件夹内没有loaddll.exe ,则会释放这个文件。用OllyDbg 打开DLL ,将会询问启动loaddll.exe ,如图13.42所示。然后链接库被加载并停在程序的入口(ModuleEntryPoint ),现在就可以正常调试DLL 程序了。

rsa算法对字符串的加密解密

#include #include /*类型定义*/ typedef long int li_ELEMTYPE; typedef int i_ELEMTYPE; typedef char c_ELEMTYPE; /*宏定义*/ #define TEXT_MAX_NUM 20 #define RSA_ENCODE_TEXT "xidianuniversity" /*RSA编解码函数*/ /* 输入输出说明:r = a^b mod c 编码1.a-------原始加密明文数据 2.b-------加密指数(p-1)(q-1) 3.c-------p*q 4.r-------加密后密文数据 解码1.a-------原始解密密文数据 2.b-------解密指数d 3.c-------p*q 4.r-------解密后明文数据 */ li_ELEMTYPE Rsa_un_enCode(li_ELEMTYPE a,li_ELEMTYPE b,li_ELEMTYPE c) { li_ELEMTYPE r = 1; b = b + 1; while(b != 1) { r = r * a; r = r % c; b--; } return r; } /*main主函数*/ int main(int argc, char **argv) { li_ELEMTYPE p,q,e,d,n,t; i_ELEMTYPE i = 0; i_ELEMTYPE acSecret_Text[TEXT_MAX_NUM]; c_ELEMTYPE acPublic_Text[TEXT_MAX_NUM]; memset(acSecret_Text, 0, sizeof(acSecret_Text));

壳的介绍以及是常用脱壳方法

一、概论 壳出于程序作者想对程序资源压缩、注册保护的目的,把壳分为压缩壳和加密壳两种 UPX ASPCAK TELOCK PELITE NSPACK ... ARMADILLO ASPROTECT ACPROTECT EPE SVKP ... 顾名思义,压缩壳只是为了减小程序体积对资源进行压缩,加密壳是程序输入表等等进行加密保护。当然加密壳的保护能力要强得多! 二、常见脱壳方法 预备知识 1.PUSHAD (压栈)代表程序的入口点, 2.POPAD (出栈)代表程序的出口点,与PUSHAD想对应,一般找到这个OEP就在附近 3.OEP:程序的入口点,软件加壳就是隐藏了OEP(或者用了假的OEP/FOEP),只要我们找到程序真正的OEP,就可以立刻脱壳。 方法一:单步跟踪法 1.用OD载入,点“不分析代码!” 2.单步向下跟踪F8,实现向下的跳。也就是说向上的跳不让其实现!(通过F4) 3.遇到程序往回跳的(包括循环),我们在下一句代码处按F4(或者右健单击代码,选择断点——>运行到所选) 4.绿色线条表示跳转没实现,不用理会,红色线条表示跳转已经实现! 5.如果刚载入程序,在附近就有一个CALL的,我们就F7跟进去,不然程序很容易跑飞,这样很快就能到程序的OEP 6.在跟踪的时候,如果运行到某个CALL程序就运行的,就在这个CALL中F7进入 7.一般有很大的跳转(大跨段),比如jmp XXXXXX 或者JE XXXXXX 或者有RETN的一般很快就会到程序的OEP。 在有些壳无法向下跟踪的时候,我们可以在附近找到没有实现的大跳转,右键-->“跟随”,然后F2下断,Shift+F9运行停在“跟随”的位置,再取消断点,继续F8单步跟踪。一般情况下可以轻松到达OEP! 方法二:ESP定律法 ESP定理脱壳(ESP在OD的寄存器中,我们只要在命令行下ESP的硬件访问断点,就会一下来到程序的OEP了!) 1.开始就点F8,注意观察OD右上角的寄存器中ESP有没突现(变成红色)。(这只是一般情况下,更确切的说我们选择的ESP值是关键句之后的第一个ESP值) 2.在命令行下:dd XXXXXXXX(指在当前代码中的ESP地址,或者是hr XXXXXXXX),按回车! 3.选中下断的地址,断点--->硬件访--->WORD断点。 4.按一下F9运行程序,直接来到了跳转处,按下F8,到达程序OEP。 方法三:内存镜像法

文件加密与解密算法

文件加密与解密算法的分析与应用 摘要:随着信息社会的到来,人们在享受信息资源所带来的巨大的利益的同时,也面临着信息安全的严峻考验。信息安全已经成为世界性的现实问题,已威胁到国家的政治、经济、军事、文化、意识形态等领域,同时,信息安全问题也是人们能否保护自己的个人隐私的关键。信息安全是社会稳定安全的必要前提条件。解决信息安全的方法是加密,所以加密解密就显得日益重要。本课题重点研究常用文件加密解密算法的基本思想及实现过程中所用到的方法、技术。同时对公钥密码体制和私钥密码体制进行了分析和研究,并对公钥密码体制和私钥密码体制的代表aes算法和des算法进行了研究和比较,最后结合常用算法设计实现了简易加密解密应用软件。 关键词:解密文件加密密码体制 des aes 中图分类号:tp314 文献标识码:a 文章编 号:1672-3791(2012)06(b)-0019-01 1 引言 1.1 文件加密与解密算法应用的意义 随着因特网、全球贸易和其它活动的增长,密码技术越来越多地用于个人的标识和认证等,它是取得信息安全性最有效的一种方法,是信息安全的核心技术。通过数据加密,人们可以有效地保证通信线路上的内容不被泄露,而且还可以检验传送信息的完整性。

对称密码算法主要用于保证数据的机密性,通信双方在加密解密过程中使用它们共享的单一密钥。最常用的是数据加密标准(des)算法,但由于des的密钥长度较短,不适合于数据加密安全性的要求。通过分组密码返回的加密数据的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换和替换输入数据。 本文在研究分析了aes加密原理的基础上着重说明了aes算法实现的具体步骤:扩展密钥的异或运算、列变换、行变换、s盒变换等,以及各步骤的轮换顺序、密钥扩展程序keyexpansion、优化等。 2 加密/解密算法的原理分析[1] 2.1 原理 对于aes算法,输入分组、输出分组、状态长度均为128比特。nb=4,该值反应了状态中32位字的列数。对于aes算法,密钥k的长度是128、192或256 bits。密钥长度表示为nk=4、6或8,反应了密钥中32位字的个数。对于aes算法,算法的轮数依赖于密钥长度。将轮数表示为nr,当nk=4时nr=10;当nk=6时nr=12;当nk=8时nr =14。对于加密和解密变换,aes算法使用的轮函数由4个不同的以字节为基本单位的变换复合而成。 (1)字节替代,利用一个替代表。(2)将状态矩阵的每一行循环移位不同的位移量。(3)将状态矩阵中每一列的数据进行混合。(4)将轮密钥加到状态上。 2.1.1 s盒变换:对输入矩阵的任一个元素a做如下变换s[a]

RSA加解密算法C语言的实现

#include #include #include #include #include #include #define MAX 100 #define LEN sizeof(struct slink) void sub(int a[MAX],int b[MAX] ,int c[MAX] ); struct slink { int bignum[MAX]; /*bignum[98]用来标记正负号,1正,0负bignum[99]来标记实际长度*/ struct slink *next; }; /*/--------------------------------------自己建立的大数运算库-------------------------------------*/ void print( int a[MAX] ) { int i; for(i=0;il2) return 1; if (l1=0;i--) { if (a1[i]>a2[i]) return 1 ; if (a1[i]

密码学-RSA加密解密算法的实现课程设计报告

密码学课程报告《RSA加密解密算法》 专业:信息工程(信息安全) 班级:1132102 学号:201130210214 姓名:周林 指导老师:阳红星 时间:2014年1月10号

一、课程设计的目的 当前最著名、应用最广泛的公钥系统RSA是在1978年,由美国麻省理工学院(MIT)的Rivest、Shamir和Adleman在题为《获得数字签名和公开钥密码系统的方法》的论文中提出的。 RSA算法是第一个既能用于数据加密也能用于数字签名的算法,因此它为公用网络上信息的加密和鉴别提供了一种基本的方法。它通常是先生成一对RSA 密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册,人们用公钥加密文件发送给个人,个人就可以用私钥解密接受。为提高保密强度,RSA密钥至少为500位长,一般推荐使用1024位。 公钥加密算法中使用最广的是RSA。RSA算法研制的最初理念与目标是努力使互联网安全可靠,旨在解决DES算法秘密密钥的利用公开信道传输分发的难题。而实际结果不但很好地解决了这个难题;还可利用RSA来完成对电文的数字签名以抗对电文的否认与抵赖;同时还可以利用数字签名较容易地发现攻击者对电文的非法篡改,以保护数据信息的完整性。此外,RSA加密系统还可应用于智能IC卡和网络安全产品。 二、RSA算法的编程思路 1.确定密钥的宽度。 2.随机选择两个不同的素数p与q,它们的宽度是密钥宽度的1/2。 3.计算出p和q的乘积n 。 4.在2和Φ(n)之间随机选择一个数e , e 必须和Φ(n)互素,整数e 用做加密密钥(其中Φ(n)=(p-1)*(q-1))。 5.从公式ed ≡ 1 mod Φ(n)中求出解密密钥d 。 6.得公钥(e ,n ), 私钥 (d , n) 。 7.公开公钥,但不公开私钥。 8.将明文P (假设P是一个小于n的整数)加密为密文C,计算方法为: C = Pe mod n 9.将密文C解密为明文P,计算方法为:P = Cd mod n 然而只根据n和e(不是p和q)要计算出d是不可能的。因此,任何人都可对明文进行加密,但只有授权用户(知道d)才可对密文解密 三、程序实现流程图: 1、密钥产生模块:

相关主题
文本预览
相关文档 最新文档