您的位置:首页 > 职场人生

记YY的一次面试经历

2016-07-14 18:11 726 查看
七月份,我投了YY的一份的实习生简历,由于我准备不足,有一些问题没有回答出来,下面我就将电话面试的问题总结一下,对自己不懂得问题进行了一些研究,希望也能给大家提供一些经验和帮助。

问题一:堆栈平衡的原理是什么

当问到这个问题的时候,我想到的就是堆栈平衡,但是他就问到原理是什么的时候,我就答不出来了,在结束之后我在百度下寻找,明白了其中的原理下面我就来说明一下

我的理解,其实堆栈平衡就是程序的调用。我们先来复习一下汇编的指令

call指令

1.向堆栈中压入下一行的地址,esp-4

2.jmp到call的子程序地址

ret指令

1.将esp+4,即将堆栈中的值出栈

2.jmp dword ptr ds:[esp-4],即jmp到当前的位置

知道了基础之后,我们就可以通过一个例子进行描述,我选择了一个upx的壳,壳的入口点的各个寄存器的值,pushad将各个寄存器的值压入栈中

<pre name="code" class="plain">EAX 00000000
ECX 0012FFB0
EDX 7C92E4F4 ntdll.KiFastSystemCallRet
EBX 7FFD3000
ESP 0012FFC4
EBP 0012FFF0
ESI 0012B5D0
EDI 005A7908
EIP 0040E8C0 UPX.<ModuleEntryPoint>
C 0  ES 0023 32位 0(FFFFFFFF)
P 1  CS 001B 32位 0(FFFFFFFF)
A 0  SS 0023 32位 0(FFFFFFFF)
Z 1  DS 0023 32位 0(FFFFFFFF)
S 0  FS 003B 32位 7FFDF000(FFF)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_NO_IMPERSONATION_TOK



到达OEP时各个寄存器的变化

<pre name="code" class="plain">EAX 00000000
ECX 0012FFB0
EDX 7C92E4F4 ntdll.KiFastSystemCallRet
EBX 7FFD3000
ESP 0012FFC4
EBP 0012FFF0
ESI 0012B5D0
EDI 005A7908
EIP 004010CC UPX.004010CC
C 0  ES 0023 32位 0(FFFFFFFF)
P 1  CS 001B 32位 0(FFFFFFFF)
A 0  SS 0023 32位 0(FFFFFFFF)
Z 1  DS 0023 32位 0(FFFFFFFF)
S 0  FS 003B 32位 7FFDF000(FFF)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_NO_IMPERSONATION_TOK



我们发现是不是除了eax,其他的值都一样,因为eax保存了当前oep的值,所以eax有变化

pushed

0040E8C0 >  60              pushad
0040E8C1    BE 15B04000     mov esi,UPX.0040B015
将各个寄存器的数据压栈,其结果如下:

<pre name="code" class="plain">EDI 005A7908
ESI 0012B5D0
EBP 0012FFF0
ESP 0012FFC4
EBX 7FFD3000
EDX 7C92E4F4
ECX 0012FFB0
EAX 00000000




popad

0040E8C0 >  60              pushad
0040E8C1    BE 15B04000     mov esi,UPX.0040B015
结果就是到达oep时的各个寄存器的值

这个时候我想大家就明白了,其实ESP定律就是完成了一次调用子程序的过程。在这里关键的地方是:如果我们要返回父程序,则当我们在堆栈中进行堆栈的操作的时候,一定要保证在RET这条指令之前,ESP指向的是我们压入栈中的地址

问题二:全局变量在堆栈中的变化

下面这段代码是我在VC++6.0进行调试时进入反汇编代码是遇到的,我发现不管什么样的函数,都有这样的一段代码,上网查询发现他是函数框架,也就说这个框架是函数执行时必须的

esp指向的地方就是堆栈

00401020   push        ebp   /ESP-4,并将ebp的值写入esp内存中
00401021   mov         ebp,esp  /esp的值付给ebp
00401023   sub         esp,40h  /开辟一个40h大的空间
00401026   push        ebx
00401027   push        esi
00401028   push        edi
00401029   lea         edi,[ebp-40h]
0040102C   mov         ecx,10h   /循环10次
00401031   mov         eax,0CCCCCCCCh  /eax的值为0xCCCCCCCCh
00401036   rep stos    dword ptr [edi] /ESP+4,重复将EAX的值付给edi的内存中
8:        return 0;
00401038   xor         eax,eax   /eax清零
9:    }
0040103A   pop         edi
0040103B   pop         esi
0040103C   pop         ebx
0040103D   mov         esp,ebp
0040103F   pop         ebp
00401040   ret


#include "stdafx.h"
int fun()
{
return 0;
}
int main(int argc, char* argv[])
{
fun();

return 0;
}


我们画出他的堆栈变化示意图:

0018FEA0  40 FF 18 00  @...     /push ebx

0018FEA4  80 10 40 00  ..@.    /push esi

0018FEA8  00 E0 FD 7F  .帻.   /push edi

0018FEAC  CC CC CC CC  烫烫

0018FEB0  CC CC CC CC  烫烫

0018FEB4  CC CC CC CC  烫烫

0018FEB8  CC CC CC CC  烫烫

0018FEBC  CC CC CC CC  烫烫

0018FEC0  CC CC CC CC  烫烫

0018FEC4  CC CC CC CC  烫烫

0018FEC8  CC CC CC CC  烫烫

0018FECC  CC CC CC CC  烫烫

0018FED0  CC CC CC CC  烫烫

0018FED4  CC CC CC CC  烫烫

0018FED8  CC CC CC CC  烫烫

0018FEDC  CC CC CC CC  烫烫

0018FEE0  CC CC CC CC  烫烫

0018FEE4  CC CC CC CC  烫烫

0018FEE8  CC CC CC CC  烫烫

0018FEEC  40 FF 18 00  @...    /push ebp

我们会发现这是一个循环的过程,esp-40h开辟出一个空间,eax的值将所开辟的内存值都赋值0xCCCCCCCC,这个想明白的话,那变量是如何变换的也就简单了,我们只需要在函数中赋值相应的变量,参数或者表达式就可以了。

#include "stdafx.h"
int fun2(int a,int b)
{
return a+b;
}
int fun1(int a,int b)
{
fun2(5,6);
return a+b;

}
int fun(int a,int b)
{
int r;
r=a+b;
fun1(3,4);
return 0;
}
int main(int argc, char* argv[])
{
fun(1,2);

return 0;
}
VC++6.0部分的汇编代码:

15:   int fun(int a,int b)
16:   {
004010B0   push        ebp
004010B1   mov         ebp,esp
004010B3   sub         esp,44h
004010B6   push        ebx
004010B7   push        esi
004010B8   push        edi
004010B9   lea         edi,[ebp-44h]
004010BC   mov         ecx,11h
004010C1   mov         eax,0CCCCCCCCh
004010C6   rep stos    dword ptr [edi]
17:       int r;
18:       r=a+b;
004010C8   mov         eax,dword ptr [ebp+8]
004010CB   add         eax,dword ptr [ebp+0Ch]
004010CE   mov         dword ptr [ebp-4],eax
19:       fun1(3,4);
004010D1   push        4
004010D3   push        3
004010D5   call        @ILT+5(fun1) (0040100a)
004010DA   add         esp,8
20:       return 0;
004010DD   xor         eax,eax
我们在VC中进入调试就会发现一个重要的变化     ebp-4的位置为第一个变量的位置,ebp+8的位置为第一个参数的位置,大家可以自己画一下堆栈图,而且每一个函数都和我上面所说框架的相同,而且是循环的。而我以前从来没有注意到

,面试就吃亏了。

当然了问题不只是这两个,还有对软件破解的流程,脱壳的方法,以及用c语言编写过那些东西等等。我的编程能力并不是特别的好,所以在c语言上的问题也没有回答好。这次的面试也给我很大的启发   1.学习要注重深度,而非广度,原理性的知识要弄懂,不可一知半解。2.复习c语言,对c语言不仅要会用,这要理解函数背后的运行原理。所以接下来还要继续努力。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: