zoukankan      html  css  js  c++  java
  • 病毒实验二

    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的寄存器状态
    • 参考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;
    }
    
    ========================if i have some wrong, please give me a message, thx.========================
  • 相关阅读:
    SQLite 版本引发的 Python 程序调用问题
    从0到10亿,微信后台架构及基础设施设计与实践!
    从Oracle到PostgreSQL:动态性能视图 vs 标准统计视图
    第一章 准备工作
    Swagger2简介
    如何查询numpy,scipy,matplotlib等的版本和安装位置
    完美解决ImportError: cannot import name '_validate_lengths'报错问题
    完美解决AttributeError: module 'scipy.misc' has no attribute 'imread'报错问题
    线上课堂:ernetes Operator开发范式
    Bomb Enemy 炸弹人
  • 原文地址:https://www.cnblogs.com/ailx10/p/5251621.html
Copyright © 2011-2022 走看看