邪恶八进制信息安全团队技术讨论组's Archiver

sunwear 2005-12-16 10:53

[转载]Short introduction to EPO

<P><SPAN id=post1 style="COLOR: #000000; FONT-SIZE: 12px">信息来源:<A href="http://www.retcvc.com">www.retcvc.com</A></SPAN></P>
<P><SPAN id=post1 style="COLOR: #000000; FONT-SIZE: 12px"></SPAN></P>
<P><SPAN id=post1 style="COLOR: #000000; FONT-SIZE: 12px">Short introduction to EPO<BR><BR>EPO stands for Entry Point Obscured .<BR><BR>What does it mean? <BR>------------------<BR><BR>A normal program contains a lots of Api calls<BR><BR>for example:<BR><BR>      push 0<BR>Source:<BR>      call ExitProcess     <BR><BR>if we replace this "Api call" by a virus call we have got an example of<BR>what is E.P.O<BR><BR>But the Api call has to be executed<BR><BR>look at the next diagram:<BR><BR>                <BR>          Call (Api call before infection)<BR>       Source -----------------------------> Aim (go to Api address)<BR>        |                   ^<BR>        |                   |<BR>        |                   |<BR>        | Call (after infection)       |Jump<BR>        |                   |<BR>        |                   |<BR>        |                   | <BR>        V                   |<BR>      BeginningOfVirus           EndOfVirus<BR><BR><BR>The call is performed from Source address. <BR>in the host the called address is Aim<BR>We change the called address.Now, it's BeginningOfVirus address.<BR><BR>When the virus has terminated its job, it performs a jump to the <BR>"Aim" address in the host program.<BR><BR>Now, the programs looks like:<BR><BR>  <BR>    push 0<BR>Source:<BR><BR>    call BeginningOfVirus<BR>   <BR>    [...]<BR><BR>BeginningOfVirus:<BR>    <BR>    pusha       ;save registers    <BR>    <BR>    < Virus Code ><BR><BR>    popa       ;restore registers <BR><BR>    jmp Aim      ;go to the inital place<BR><BR><BR>We need to know a little bit more about the opcodes of some instructions,<BR>performing a jump or a call<BR><BR>Especially those ones:<BR><BR>I) <BR>*****<BR><BR>Source:<BR><BR>jmp Aim<BR><BR>[...]<BR><BR>Aim:<BR><BR><BR>%% coded as : db 0e9h<BR>       dd offset Aim - offset Source - 5<BR><BR>(there exist others direct jmp, but no needed for our purposes)<BR>It doesn't matter if Source address is greater than Aim one, the code works too.<BR><BR>II)<BR>*****<BR><BR>source:<BR><BR>jmp [Aim] ;jmp to the address contained in dword Aim<BR><BR>[...]<BR><BR>Aim:<BR>dd X<BR><BR><BR>%% coded as: db 0ffh,25h<BR>      dd offset Aim <BR><BR>III)<BR>*****<BR><BR>source:<BR><BR>call Aim<BR><BR><BR><BR>%% coded as: db 0e8h<BR>      dd offset Aim - offset Source - 5<BR><BR>In fact, only the last two instructions are used in the apis call process per-<BR>formed by Windows. But the direct (far) jump opcode is needed in what is following.<BR><BR>How does a simple EPO technic works?<BR>------------------------------------<BR><BR>First we search for byte e8h,<BR><BR>its surely the beginning of "Call Aim" instruction. (that is, db 0e8h following<BR>by a dword X)<BR><BR>We need to do that, to find a file pointer ,pointing to the entry point of<BR>program.<BR><BR>In the different headers of a Portable Executable (PE for short) we can<BR>find the virtual address (VA for short) of entry point of program<BR>and VA of code section (we need the first VA to find this one, because<BR>code section isn't necessary the first section)<BR><BR>We can get the PointerToRawData of code section. (it is located in<BR>section code header). It's a file pointer.<BR><BR>VA isn't a file pointer, a VA + ImageBase value gives you a memory address.<BR><BR>A file pointer to entry point is got from the formula:<BR><BR>%%% Entry Point Pointer=  PointerToRawdata of Code Section<BR>          <BR>            + (VA of Entry Point - VA of Code Section)<BR><BR>Using this pointer ( a dword), we can scan the section code to find<BR>e8h byte.<BR><BR>Are we sure the byte e8h (we just find) the first byte of a call?<BR>No we aren't!<BR><BR>Here is the correct layout of an Api call:<BR><BR>Instructions:       opcodes:<BR><BR><BR>call Aim          db 0e8 <BR>             dd x<BR><BR>[...]<BR><BR>Aim:<BR><BR>jmp [YYYY]         dw 0ff25h<BR>             dd "YYYY"<BR><BR><BR>"Aim" isn't an Api address at all!<BR><BR>However, we have a method to check if a call is an api call or not.<BR>We have just to check if the word ff25h is at the address "Aim"!<BR><BR>First, we need to compute the VA of "Aim"<BR><BR>VA Aim - VA of "0e8h" byte -5=X<BR><BR>then we've got :<BR><BR>         VA Aim= X+ VA of "0e8h"+5<BR><BR>The VA of Aim is knew. We need to get a file pointer for the VA of Aim.<BR>There is no information in the different headers of the PE file to know dir-<BR>ctly where is "jmp [YYYY]" <IMG alt=Sad src="http://www.retcvc.com/cgi-bin/non-cgi/emoticons/sad.gif"><BR><BR>The VA of Aim is used to know in wich section we can find it.<BR><BR>(Sometime, this VA isn't in the mapped PE file.<BR>The reason is quite simple, the e8 byte wasn't an opcode for a Call at all!)<BR><BR><BR>However, most of the time it's in code section itself.<BR><BR>Let's assume it. We 've got the formula:<BR><BR>Pointer to Aim = PointerToRawdata of Code Section<BR>        +(VA of Aim - VA of Code Section)<BR><BR><BR>Let's assume this value (a dword) is in EAX register<BR>and we have mapped the PE target in memory:<BR><BR>       add eax,BaseAddressOfMapping<BR>       cmp dword ptr [eax],25ffh <BR>       jnz NoJmpHere        <BR><BR>do the test we need.        <BR><BR>(before to perform this test, we have to be sure the address in eax is in<BR>the file itself, else fault protection page will surely occure!)<BR><BR>Now ,we build the new "call" to replace the previous one.<BR><BR>We want:<BR><BR>Instructions:           opcodes:<BR><BR>Source:<BR>call Beginning of virus      db 0e8h<BR>                dd Y<BR><BR><BR>Since ,<BR>VA of beginning of virus- VA of Source =Y - 5<BR><BR>Then :<BR><BR>    Y=VA of Beginning of Virus - VA of Source + 5<BR><BR><BR>Let's assume VA of the end of virus code is EndOfVirus<BR><BR>We want to jump to real aim of the Api call<BR><BR>We Want :<BR><BR><BR>Instructions:       Opcodes:<BR><BR>EndOfVirus:        <BR>     <BR>jmp Aim          db 0e9h<BR>            dd Z<BR><BR>We compute the needed dword appearing in jump instruction: db 09eh,dd Z<BR>(Z is the unknown dword we are searching for).<BR><BR>Once more we have:<BR><BR>VA Aim- VA of EndOfVirus=Z-5<BR><BR>then:<BR><BR>     Z=VA Aim -VA EndOfVirus+5<BR><BR><BR>Example of code obtained:<BR><BR><BR>before infection:<BR><BR>Source:<BR>db 0e8h    ;<BR>dd offset Aim ;Call Aim<BR><BR>[...]<BR><BR>Aim:<BR><BR><BR>After infection:<BR><BR><BR>db 0e8h                    ;<BR>dd offset BeginningOfVirus -offset Source+5 ;call BeginningOfVirus<BR><BR>[...]<BR><BR>Aim:<BR><BR>[...]<BR><BR>BeginningOfVirus:<BR><BR>[...]<BR><BR>EndOfVirus:<BR>db 0e9h <BR>dd offset Aim-Offset EndOfVirus+5<BR><BR>I hope this tutorial will help you to understand a basic EPO technic.<BR>Up to now, antiviruses scanners seems to have a bad trip to detect infected<BR>files by a virus using EPO. However this article can be used for AV use too!<BR>So this basic technic will be outdated soon , i suppose.<BR>But there is two things you can do, to make the job of AV more harder.<BR>Think by yourself...answers are included in this article </SPAN></P>

页: [1]
© 1999-2008 EvilOctal Security Team