病毒实验二

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\n",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)\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 <stdio.h>
#include <stdlib.h>
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的寄存器状态
  • 参考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\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
#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\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;
}
posted @ 2016-03-07 19:32  ailx10  阅读(250)  评论(0编辑  收藏  举报