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.c
int 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=1
s: //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 end
aa:
mov eax,ecx
jmp end
end:
pop ebx;
}
}
int main()
{
printf("%d
",fib(20));
}
part3
- 请使用汇编语言编写程序 采用递归算法来计算斐波那契数
//f(n)=f(n-1)+f(n-2) f(1)=1 f(0)=0
//fib2.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char** argv){
int n,r;
if(argc<2){
printf("usage:%s number(<40)
",argv[0]);
return -1;
}
n=atoi(argv[1]);
__asm{
//evaluate r=f(n)
}
printf("fib(%d)=%d
",n,r);
return 0;
}
要求:
- 完成fib2.c中的汇编代码
- 采用递归调用来计算数列
- 程序输出示例:
D:>fib 6
fib(6)=8
part3报告
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
int n, r;
if (argc < 2) {
printf("Usage: %s number(<40)
", 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, 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的寄存器状态
- eax是局部变量或函数返回值 寄存器的状态都保存在结构体里面了
- swtch函数前面的__declspec(naked)为何不能删除
-
参考coroutine.c 编写c语言程序tri-tasks.c 完成下面的功能:
请分别创建三个任务A B C
其中A输出10次数字1
B输出9次数字2
C输出8次数字3
要求三个任务交替输出
part4报告
//coroutine.c
#include <stdio.h>
struct 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
");
swtch(&A, &M);
printf("A: 2
");
swtch(&A, &M);
printf("A: 3
");
swtch(&A, &M);
printf("A: 4
");
swtch(&A, &M);
printf("A: 5
");
swtch(&A, &M);
printf("A: 6
");
swtch(&A, &M);
printf("A: 7
");
swtch(&A, &M);
}
int main()
{
int stackA[1024];
A.eip = (int)taskA;
A.esp = (int)(&stackA[1023]);
swtch(&M, &A);
printf("M: 1
");
swtch(&M, &A);
printf("M: 2
");
swtch(&M, &A);
printf("M: 3
");
swtch(&M, &A);
printf("M: 4
");
swtch(&M, &A);
printf("M: 5
");
swtch(&M, &A);
printf("M: 6
");
return 0;
}
//tri-tasks.c
#include <stdio.h>
struct 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
");
swtch(&A, &B);
}
printf("A:1
");
swtch(&A, &B);
printf("A:1
");
swtch(&A, &M);
}
void taskB()
{
int j;
for(j=0;j<8;j++)
{
printf("B:2
");
swtch(&B, &M);
}
printf("B:2
");
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
");
swtch(&M, &A);
}
return 0;
}