title: viruslab2
date: 2016-01-02 20:38:00 categories: virus tags: virus ---工具:vs2012 ollydbg
part1
- 本程序附带一个hello.exe程序 使用ollydbg调试该程序完成下列任务
- 列出hello.exe加载到内存之后 共被分为几个节 每个节的名字是什么 所占内存的起始地址
- 观察地址0x0040100F这个地址对应的指令
- 在0x0040100F设置断点 观察栈中[ebp-4]放置的32位数值
- 单步执行到user32.dll中的MessageBoxA函数 观察函数体 写出MessageBoxA函数的前5条指令和后3条指令
part2
- 编写内嵌汇编的程序fib1.c 迭代计算f(n)的值
//fib1.cint fib(int n){ __asm{ //evaluate fib(n) }}int main(){ //print fib(20)}
要求:
- 填入所缺的汇编代码
- 编译链接fib1.c 生成fib1.exe 计算输出fib(20)
- 单步跟踪程序运行 记录填写一下信息
- 程序被加载到内存的基地址
- fib函数第一条指令的地址
- fib函数被第一次调用时的栈帧基址
- 在调用printf函数之前的栈顶地址
part2报告
int fib(int n) {__asm { mov ecx,dword ptr [ebp+8] //参数1存入ecx cmp ecx,0 //比较是否等于0 je aa //相等则跳转到aa cmp ecx,1 //比较是否等于1 je aa sub ecx,1 //ecx-1 mov eax,0 //eax=0 push ebx; //ebx压栈保护 mov ebx,1 //ebx=1s: //0 1 1 2 3 5 8 13 21 add eax,ebx //eax+=ebx mov edx,eax //交换eax和ebx的值 使得ebx保存较大的值 mov eax,ebx mov ebx,edx loop s //ecx-- 后ecx=0退出循环 mov eax,ebx jmp endaa: mov eax,ecx jmp endend: pop ebx;}}int main(){ printf("%d\n",fib(20));}
part3
- 请使用汇编语言编写程序 采用递归算法来计算斐波那契数
//f(n)=f(n-1)+f(n-2) f(1)=1 f(0)=0//fib2.c#include#include int main(int argc,char** argv){int n,r;if(argc<2){ printf("usage:%s number(<40)\n",argv[0]); return -1;}n=atoi(argv[1]);__asm{ //evaluate r=f(n)}printf("fib(%d)=%d\n",n,r);return 0;}
要求:
- 完成fib2.c中的汇编代码
- 采用递归调用来计算数列
- 程序输出示例: D:>fib 6 fib(6)=8
part3报告
#include#include int main(int argc, char *argv[]){ int n, r; if (argc < 2) { printf("Usage: %s number(<40)\n", argv[0]); return -1;} n = atoi(argv[1]); __asm { mov eax,dword ptr [n] //n是fib()的输入 push eax call fib add esp,4 mov dword ptr [r],eax //r是fib()的输出 jmp endd fib: push ebp mov ebp,esp sub esp,0x48 push ebx push esi push edi mov ecx,dword ptr [ebp+8] cmp ecx,0 //fib(0) je aa cmp ecx,1 //fib(1) je aa sub ecx,1 push ecx call fib pop ecx mov ebx,eax //ebx=eax sub ecx,1 push ecx call fib pop ecx add eax,ebx //eax=eax+ebx jmp end aa: mov eax,ecx jmp end end: pop edi pop esi pop ebx mov esp,ebp pop ebp ret endd:} printf("fib(%d) = %d\n", n, r); return 0;}
part4
- 实时多任务
- 假设我们把main函数看成做是程序的主任务 那么我们可以创建一个新的任务来模拟多线程 运行不同的程序代码 main函数在运行之前 系统已经为main函数分配了一个运行栈 如果我们需要创建一个新的任务 A 那么我们需要手动为A分配一段内存空间作为A任务的运行栈 然后我们可以通过一个切换操作swtch(..)就可以实现main任务与A任务的交替并发执行
- 运行下面命令编译链接coroutine.c 并检查输出结果 >cl /c /GS- coroutine.c >link coroutine.obj
- 阅读理解coroutine.c 使用ollydbg跟踪运行程序 回答下面问题
- swtch函数前面的__declspec(naked)为何不能删除
- 作用是告诉编译器 不需要添加任何汇编代码 否则栈的平衡会遭到破坏
- swtch函数中倒数第二条指令push [ecx]的作用是什么 压入栈中的值是什么
- to结构体的eip入栈
- 观察到ctx结构体中没有出现eax 那么请问为何切换时不要保存eax
- eax是局部变量或函数返回值 寄存器的状态都保存在结构体里面了 [提示]:ctx是一个结构体 保存cpu的寄存器状态
- swtch函数前面的__declspec(naked)为何不能删除
- 参考coroutine.c 编写c语言程序tri-tasks.c 完成下面的功能: 请分别创建三个任务A B C 其中A输出10次数字1 B输出9次数字2 C输出8次数字3 要求三个任务交替输出
part4报告
//coroutine.c#includestruct ctx { int eip, esp, ebx, ebp;} M, A;__declspec(naked) void swtch(struct ctx *from, struct ctx *to){ __asm{ mov eax, [esp+4] //from结构体的eip存入eax pop dword ptr [eax] //出栈from结构体的eip mov [eax+4], esp //当前esp 存入 from结构体的esp mov [eax+8], ebx //当前ebx 存入 from结构体的ebx mov [eax+12], ebp //当前ebp 存入 from结构体的ebp mov ecx, [esp+4] //to结构体的eip存入当前的ecx mov ebp, [ecx+12] //to结构体的ebp存入当前的ebp mov ebx, [ecx+8] //to结构体的ebx存入当前的ebx mov esp, [ecx+4] //to结构体的esp存入当前的esp push [ecx] //入栈to结构体的eip ret }}void taskA(){ printf("A: 1\n"); swtch(&A, &M); printf("A: 2\n"); swtch(&A, &M); printf("A: 3\n"); swtch(&A, &M); printf("A: 4\n"); swtch(&A, &M); printf("A: 5\n"); swtch(&A, &M); printf("A: 6\n"); swtch(&A, &M); printf("A: 7\n"); swtch(&A, &M);}int main(){ int stackA[1024]; A.eip = (int)taskA; A.esp = (int)(&stackA[1023]); swtch(&M, &A); printf("M: 1\n"); swtch(&M, &A); printf("M: 2\n"); swtch(&M, &A); printf("M: 3\n"); swtch(&M, &A); printf("M: 4\n"); swtch(&M, &A); printf("M: 5\n"); swtch(&M, &A); printf("M: 6\n"); return 0;}
//tri-tasks.c#includestruct ctx { int eip, esp, ebx, ebp;} M,A,B;__declspec(naked) void swtch(struct ctx *from, struct ctx *to){ __asm{ mov eax, [esp+4] pop dword ptr [eax] mov [eax+4], esp mov [eax+8], ebx mov [eax+12], ebp mov ecx, [esp+4] mov ebp, [ecx+12] mov ebx, [ecx+8] mov esp, [ecx+4] push [ecx] ret }}void taskA(){ int i; for(i=0;i<8;i++) { printf("A:1\n "); swtch(&A, &B); } printf("A:1\n "); swtch(&A, &B); printf("A:1\n "); swtch(&A, &M);}void taskB(){ int j; for(j=0;j<8;j++) { printf("B:2 \n"); swtch(&B, &M); } printf("B:2 \n"); swtch(&B, &A);}int main(){ int stackA[1024]; int stackB[1024]; int k; B.eip=(int)taskB; B.esp=(int)(&stackB[1024]); A.eip = (int)taskA; A.esp = (int)(&stackA[1024]); swtch(&M, &A); for(k=0;k<8;k++) { printf("C:3 \n"); swtch(&M, &A); } return 0;}