免杀对抗从0开始(一)

admin 2024年10月24日22:20:07评论10 views字数 14956阅读49分51秒阅读模式
🔥师傅您好:为了确保您不错过我们的最新网络安全资讯、技术分享和前沿动态,请将我们设为星标🌟!这样,您就能轻松追踪我们的每一篇精彩内容,与我们一起共筑网络安全防线!感谢您的支持与关注!💪
免责声明:文章所涉及内容,仅供安全研究教学使用,由于传播、利用本文所提供的信息而造成的任何直接或间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。

一线红队带你从O到无限进步  

本文章所涉及所有内容均是大佬上课说讲的内容,其中做了一下基础的补充,高深的技术后面会慢慢在文章中出现

一线在职红队在线性感分享技术,从c语言开始基础带你慢慢进入终端对抗(免杀但是不止免杀)的大门。

今天分享大佬对R3层杀软对抗看法,以及环境搭建。

我们先看看大佬对当下杀软的看法以及对抗的细节概述。

流量层面 - cdn            
           
           行为层面 - 静态行为- 静态查杀            
           
           动态查杀方式 - iat表 字符串(危险exe危险的字符串的hash值被标记了) 签名(5k~200k不等) 熵值 白+黑 exe            
           
           行为查杀方式 - 启发式查杀:loader加载shellcode 使用函数的调用链            
           
           行为查杀  进程注入 注册表 添加用户 添加计划任务(不适用与启发式)    bof - 走api形式(不用起cmd或者powershell)            
           
           内存查杀 卡巴斯基(做的最好) 诺顿 360 火绒(一般只是扫rwx区)            
           
静态(主要目标:赛门铁克)沙箱牛逼            
           
静态 eset (流量监测严格)+ bitdefender            
           
杀软特点(不会扫自己的签名进程)

编程规范            
           
google规范            
           
linux命名:变量命名:buff_len            
           
                  函数命名:read_buffer()            
           
windows命名:变量命名:buffLen            
           
                                                函数命名:ReadBuffer            
int i            
           
char str =  "1";//utf - 8            
           
WCHAR wStr = L"1";//utf - 16            
           
BOOL bRet = FALSE //TRUE            
           
char* pStr = NULL;            
           
WCHAR* pWstr = NULL;            
           
W函数适用于亚太地区文字  A函数适用于英美    

这里写出编程规范是大佬一直强调编程的规范重要性。

下面给出的就是编程环境搭建的步骤以及截图:

首先我们需要一个干净的win10虚拟机环境(需要英文版),不要windowsdefender这里杀软存在。

            

接下来是c语言一些基础讲解

数据类型  

1.整型  

作用:整型变量表示整数类型的数据。

语法:

int a = 10;

C++中共有4种表示整型的类型,区别在于所占内存空间可表示的取值范围不同。

数据类型

占用空间

short(短整型)

2字节

int(整型)

4字节

long(长整形)

4字节

long long(长长整形)

8字节

2.浮点型(实型)  

作用:浮点型变量表示小数类型的数据。

语法:    

float f1 = 3.1415926535f;                
double d1 = 3.1415926535;

浮点型变量分为两种,区别在于表示的有效数字范围不同。                
(1)单精度float:4字节                
(2)双精度double:8字节

数据类型

占用空间

float

4字节

double

8字节

3.字符型  

C和C++语言中,字符型变量只占用1个字节。                
字符型变量是将对应的
ASCII编码存放至内存,而不是字符本身。

作用:字符型变量可表示单个字符。                
语法:

char ch = 'a';

4.字符串型  

作用:表示一串字符

语法:

           //C风格字符串                
           char cStr[] = "hello c str";                
           cout << cStr << endl;                
               
           //C++风格字符串                
           string cppStr = "hello cpp str";                
           cout << cppStr << endl;

(1)C风格字符串char 变量名[] = "字符串值";                
(2)
C++风格字符串string 变量名 = "字符串值";

5.布尔类型 bool  

作用:布尔数据类型表示真或假的值。

语法:

           bool flag = true;                
           cout << flag << endl;           // 1(真)                
               
           flag = false;                
           cout << flag << endl;           // 0(假)    

bool类型占1个字节大小,且只有两个值:                
(1)true: 真(本质是1)                
(2)false:假(本质是0)

5.转义字符  

作用:表示一些特殊的无法直接显示的ASCII字符。                
常用的转义字符有:
n \ t

转义字符

含义

ASCII**码值(十进制)**

a

警报

007

b

退格(BS) ,将当前位置移到前一列

008

f

换页(FF),将当前位置移到下页开头

012

n

换行(LF) ,将当前位置移到下一行开头

010

r

回车(CR) ,将当前位置移到本行开头

013

t

水平制表(HT) (跳到下一个TAB位置)

009

运算符  

运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 语言内置了丰富的运算符,并提供了以下类型的运算符:

·算术运算符

·关系运算符

·逻辑运算符

·位运算符

·赋值运算符

·杂项运算符

算术运算符  

                  

运算符

描述

实例

+

把两个操作数相加

A + B 将得到 30

-

从第一个操作数中减去第二个操作数

A - B 将得到 -10

*

把两个操作数相乘

A * B 将得到 200

/

分子除以分母

B / A 将得到 2

%

取模运算符,整除后的余数

B % A 将得到 0

++

自增运算符,整数值增加 1

A++ 将得到 11

--

自减运算符,整数值减少 1

A-- 将得到 9

关系运算符  

int A = 10;

int B = 20;

运算符

描述

实例

==

检查两个操作数的值是否相等,如果相等则条件为真。

(A == B) 为假。

!=

检查两个操作数的值是否相等,如果不相等则条件为真。

(A != B) 为真。

>

检查左操作数的值是否大于右操作数的值,如果是则条件为真。

(A > B) 为假。

<

检查左操作数的值是否小于右操作数的值,如果是则条件为真。

(A < B) 为真。

>=

检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。

(A >= B) 为假。

<=

检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。

(A <= B) 为真。

                  

逻辑运算符  

int A = 1;

int B = 0;

运算符

描述

实例

&&

称为逻辑与运算符。如果两个操作数都非零,则条件为真。

(A && B) 为假。

||

称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。

(A || B) 为真。

!

称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。

!(A && B) 为真。

              

位运算符  

&、 | 和 ^ 的真值表如下所示:

p

q

p & q

p | q

p ^ q

0

0

0

0

0

0

1

0

1

1

1

1

1

1

0

1

0

0

1

1

              

赋值运算符  

运算符

描述

实例

=

简单的赋值运算符,把右边操作数的值赋给左边操作数

C = A + B 将把 A + B 的值赋给 C

+=

加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数

C += A 相当于 C = C + A

-=        

减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数

C -= A 相当于 C = C - A

*=

乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数

C *= A 相当于 C = C * A

/=

除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数

C /= A 相当于 C = C / A

%=

求模且赋值运算符,求两个操作数的模赋值给左边操作数

C %= A 相当于 C = C % A

<<=

左移且赋值运算符

C <<= 2 等同于 C = C << 2

>>=

右移且赋值运算符

C >>= 2 等同于 C = C >> 2

&=

按位与且赋值运算符

C &= 2 等同于 C = C & 2

^=

按位异或且赋值运算符

C ^= 2 等同于 C = C ^ 2

|=

按位或且赋值运算符

C |= 2 等同于 C = C | 2

              

杂项运算符 ↦ sizeof & 三元  

列出 C 语言支持的其他一些重要的运算符

运算符

描述

实例

sizeof()

返回变量的大小。

sizeof(a) 将返回 4,其中 a 是整数。

&

返回变量的地址。

&a; 将给出变量的实际地址。

*

指向一个变量。

*a; 将指向一个变量。

? :

条件表达式

如果条件为真 ? 则值为 X : 否则值为 Y

C语言运算符优先级    

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

*[]*

数组下标

数组名[常量表达式]

左到右

--

*()*

圆括号

(表达式)/函数名(形参表)

--

                        

                        

*.*

成员选择(对象)

对象.成员名

--

                        

                        

*->*

成员选择(指针)

对象指针->成员名

--

                        

                        

                        

                        

                        

                        

                        

                        

2

*-*

负号运算符

-表达式

*右到左*

单目运算符

*~*

按位取反运算符

~表达式

                        

                        

                        

*++*

自增运算符

++变量名/变量名++

                        

                        

                        

*--*

自减运算符

--变量名/变量名--

                        

                        

                        

***

取值运算符

*指针变量

                        

                        

                        

*&*

取地址运算符

&变量名

                        

                        

                        

*!*

逻辑非运算符

!表达式

                        

                        

                        

*(**类型**)*

强制类型转换

(数据类型)表达式

--

                        

                        

*sizeof*

长度运算符

sizeof(表达式)

--

                        

                        

                        

                        

                        

                        

                        

                        

3

*/*

表达式/表达式

左到右

双目运算符

***

表达式*表达式

                        

                        

                        

*%*

余数(取模)

整型表达式%整型表达式        

                        

                        

                        

4

*+*

表达式+表达式

左到右

双目运算符

*-*

表达式-表达式

                        

                        

                        

5

*<<*

左移

变量<<表达式

左到右

双目运算符

*>>*

右移

变量>>表达式

                        

                        

                        

                        

                        

                        

                        

                        

                        

6

*>*

大于

表达式>表达式

左到右

双目运算符

*>=*

大于等于

表达式>=表达式

                        

                        

                        

*<*

小于

表达式<表达式

                        

                        

                        

*<=*

小于等于

表达式<=表达式

                        

                        

                        

7

*==*

等于

表达式==表达式

左到右

双目运算符

*!**=*

不等于

表达式!= 表达式

                        

                        

                        

                        

                        

                        

                        

                        

                        

8

*&*

按位与

表达式&表达式

左到右

双目运算符

9

*^*

按位异或

表达式^表达式

左到右

双目运算符

10

*|*

按位或

表达式|表达式

左到右

双目运算符

11

*&&*

逻辑与

表达式&&表达式

左到右

双目运算符

12

*||*

逻辑或

表达式||表达式

左到右

双目运算符

                        

                        

                        

                        

                        

                        

13        

*?:*

条件运算符

表达式1?表达式2: 表达式3

*右到左*

三目运算符

                        

                        

                        

                        

                        

                        

14

*=*

赋值运算符

变量=表达式

*右到左*

--

*/=*

除后赋值

变量/=表达式

--

                        

                        

*=**

乘后赋值

变量*=表达式

--

                        

                        

*%=*

取模后赋值

变量%=表达式

--

                        

                        

*+=*

加后赋值

变量+=表达式

--

                        

                        

*-=*

减后赋值

变量-=表达式

--

                        

                        

*<<=*

左移后赋值

变量<<=表达式

--

                        

                        

*>>=*

右移后赋值

变量>>=表达式

--

                        

                        

*&=*

按位与后赋值

变量&=表达式

--

                        

                        

*^=*

按位异或后赋值

变量^=表达式

--

                        

                        

*|=*

按位或后赋值

变量|=表达式

--

                        

                        

                        

                        

                        

                        

                        

                        

15

*,*

逗号运算符

表达式,表达式,…

左到右

--

同一优先级的运算符,运算次序由结合方向所决定                
简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
   

课程知识点讲解  

1.const 变量  

 const int d = 10“(const代表整个作用域中的d都是定值10)

解释:const 变量              
             
const 变量指的是,此变量的值是只读的,不应该被改变。              
             
如果我们在程序中试图修改 const 变量的值,在编译的时候,编译器将给出错误提示。              
             
正因为 const 变量的值在给定以后不能改变,所以 const 变量必须被初始化。

2.函数入口点  

函数入口点默认是main函数,程序运行时是从main函数开始运行,没有特殊需求的情况不要修改

如果需要修改就需要再编辑器中修改,vs和vc位置不一样这里我们演示vs的修改位置

先打开项目的属性页面

然后再点开链接器界面,选择所以选项的选项卡,然后翻找一下就可以看到入口点配置,在这里就可以修改你的入口点函数    

免杀对抗从0开始(一)

3.格式说明符  

通常来说使用格式说明符的输出函数是printf(),输入函数是scanf_s(),这两个函数的用法不在过多描述,接下来看一下格式说明符

·%d%i: 输出十进制整数。

·%u: 输出无符号十进制整数。

·%f: 输出浮点数。

·%s: 输出字符串。

·%c: 输出单个字符。

·%x%X: 输出十六进制数。

·%o: 输出八进制数。

·%p: 输出指针地址。

上面就是格式化东西,下面用代码演示一下用法

printf("number:%d",a);              
这里的%d就是格式说明符表示已十进制整形输出,a则是输出的内容              
例如:int a  =10;              
           printf("number:%d",a);              
那么输出结果就是number:10。              
如果要打印多个数据就如下操作              
int a = 10;              
int b = 11;              
int c = 12;              
printf("number1:%d,number2:%d,number3:%d",a,b,c);              
那么结果就是number1:10,number2:11,number3:12              
其他格式说明符均是这样操作。    

计算大小的函数  

1.sizeof  

sizeof是一个单目运算符,不是函数。

sizeof返回一个对象在内存中所占的存储空间,单位是字节byte。

printf("short int=%lldn", sizeof(short));                
printf("int=%lldn", sizeof(int));                
printf("long int=%lldn", sizeof(long));                
printf("long long int=%lldn", sizeof(long long));                
printf("float=%lldn", sizeof(float));                
printf("double=%lldn", sizeof(double));                
printf("char=%lld", sizeof(char));                
               
输出效果:                
short int=2                
int=4                
long int=4                
long long int=8                
float=4                
double=8                
char=1

注意: sizeof()//sizeof包含结尾的 []这种情况一般用sizeof sizeof计算的是在内存种占用的大小(算指针在内存的大小只能用sizeof)

2.strlen  

strlen函数是C语言中的一个字符串函数,用于计算一个字符串的长度。 它的原型如下:

size_t strlen(const char *str);

其中,参数str是一个指向以字符结尾的字符串的指针,函数返回值是一个无符号整型(size_t),表示字符串的长度。

char str[] = "Hello World";                
int len = strlen(str);                
printf("Length of string: %dn", len);                
               
输出结果:                
Length of string: 11

                    

申请内存的函数  

 常用的内存申请函数有4个:malloc() calloc() HeapAlloc() VitrualAlloc()

1.malloc  

分配内存块。

语法:

void *malloc(                
   size_t size                
);

参数:

size                
要分配的字节数。

返回值:

malloc 会返回指向已分配空间的 void 指针,如果可用内存不足,则返回 NULL

例子:

double * ptd = (double * ) malloc (30 * sizeof(double));

2.calloc  

使用初始化为 0 的元素分配内存中的数组。

语法:

void *calloc(                
   size_t number,                
   size_t size                
);

参数:

number                
元素数量。                
               
size                
每个元素的长度(以字节为单位)。

返回值:

calloc 返回指向已分配空间的指针。 返回值指向的存储空间与任何类型的对象的存储适当对齐。 若要获取指向类型而非 void 的指针,请在返回值中使用类型转换。    

例子:

int* p = (int*)calloc(10,sizeof(int));

3.HeapAlloc  

从堆中分配内存块。 分配的内存不可移动。

语法:

DECLSPEC_ALLOCATOR LPVOID HeapAlloc(                
  [in] HANDLE hHeap,                
  [in] DWORD  dwFlags,                
  [in] SIZE_T dwBytes                
);

参数:

[in] hHeap                
               
要从中分配内存的堆的句柄。 此句柄由 HeapCreate 或 GetProcessHeap 函数返回。                
               
[in] dwFlags                
               
堆分配选项。 指定这些值中的任何一个都将替代使用 HeapCreate 创建堆时指定的相应值。 此参数可使用以下一个或多个值。                
               
[in] dwBytes                
               
要分配的字节数。                
               
如果 hHeap 参数指定的堆是“不可增长的”堆, 则 dwBytes 必须小于 0x7FFF8。 可以通过使用非零值调用 HeapCreate 函数来创建不可增长的堆。

返回值:

如果函数成功,则返回值是指向已分配内存块的指针。

如果函数失败并且您尚未指定 HEAP_GENERATE_EXCEPTIONS,则返回值为 NULL

例子:

char* buffer3 = NULL;                
buffer3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(calculate));

注意:HeapAlloc没有设置内存权限的设置。    

4.VitrualAlloc  

保留、提交或更改调用进程的虚拟地址空间中页面区域的状态。 此函数分配的内存会自动初始化为零。

语法:

LPVOID VirtualAlloc(                
  [in, optional] LPVOID lpAddress,                
  [in]           SIZE_T dwSize,                
  [in]           DWORD  flAllocationType,                
  [in]           DWORD  flProtect                
);

参数:

[in, optional] lpAddress                
               
要分配的区域的起始地址。 如果保留内存,则指定的地址向下舍入到分配粒度中最近的倍数。 如果内存已保留并正在提交,地址将向下舍入到下一页边界。 若要确定页面的大小和主机计算机上的分配粒度,请使用 GetSystemInfo 函数。 如果此参数 NULL,系统将确定分配区域的位置。                
               
[in] dwSize                
               
区域的大小(以字节为单位)。 如果 lpAddress 参数 NULL,则此值向上舍入到下一页边界。 否则,分配的页面将包含范围中包含一个或多个字节的所有页面,从 lpAddress 到 lpAddress+dwSize。 这意味着跨页边界的 2 字节范围会导致这两个页面都包括在分配的区域。                
               
[in] flAllocationType                
               
内存分配的类型。此参数必须包含以下值之一。                
具体参数前往微软官网查看                
               
https://learn.microsoft.com/zh-cn/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc                
               
[in] flProtect                
               
要分配的页面区域的内存保护。 如果要提交页面,则可以指定内存保护常量之一。                
               
如果 lpAddress 指定 enclave 中的地址,flProtect 不能是以下值之一:                
               
PAGE_NOACCESS                
PAGE_GUARD                
PAGE_NOCACHE                
PAGE_WRITECOMBINE                
为 enclave 分配动态内存时,flProtect 参数必须 PAGE_READWRITE 或 PAGE_EXECUTE_READWRITE。    

返回值:

如果函数成功,则返回值是页面分配区域的基址。

如果函数失败,则返回值 NULL

                

例子:

char* buffer4 = NULL;                
buffer4 = VirtualAlloc(NULL, sizeof(calculate)//需要申请的大小, MEM_COMMIT//此处理解为固定搭配一般不修改, PAGE_EXECUTE_READWRITE);//这里我们申请的权限是可读可写可执行  EXECUTE:执行权限 READ:读权限 WRITE:写权限

 总结:前三者没有申请的内存没有执行权限,VitrualAlloc有,每个函数都有适用场景

字符串拷贝以及内存拷贝的函数  

1.strcpy()(字符串拷贝常用函数)  

使用头文件:#include

定义:char *strcpy(char *dest, const char *src);

参数:

destinin:目标字符数组;                
source:源字符数组;

函数说明:strcpy()会将参数src 字符串拷贝至参数dest 所指的地址。 用于对字符串进行复制,识别到字符串的结束符号‘’自动停止

返回值:返回参数dest 的字符串起始地址。

注意:

参数 dest 的内存空间要足够大,否则拷贝可能会造成缓冲溢出。                
strcpy() 在复制结束后会添加结束符,这点和strncpy()不同

免杀对抗从0开始(一)

2.memcpy()(内存拷贝常用函数)  

使用头文件:C语言:#includeC++:#include

定义:void memcpy(void *dest, const void *src, size_t n);

参数:    

destinin:目标地址;                
source:源地址;                
n:复制的字节长度。

函数说明:memcpy()复制 src 所指的内存数据的 n 个字节到 dest所指的内存地址上。也就是从源地址复制n 个字节到目标地址

第一个和第二个指针都是void型且第二个指针不能被修改,第三个参数是需要拷贝的内存长度按字节记。

返回值:返回指向 dest 的指针。返回的指针类型是void。

注意:

memcpy()并不限制被复制的数据类型,只是逐字节地进行复制,任何数据类型都可以进行复制,例如字符数组、整型、结构体、类等

memcpy() 会完整的复制 num个字节,不会遇到‘’而结束,这点与 strcpy() 不同

通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

                

条件判断函数  

1.if  

语法:

if (表达式)                
{                
           语句                
}

例子:

#include                
void main()                
{                
     int a = 10;                
     int b = 20;                
     if(a>b)                
     {                
     printf("max = %dn",a);                
     }                
     if(a        <b)< span>        </b)<>                  
     {                  
     printf("max = %dn",b);                  
     }                  
}                  
如果满足第一个if的表达式那么就打印a的值,如果满足第二个if的表达式那么就打印b的值                  
上面的结果是max = 20;          

2.if_else  

默认在if和else语句中都只控制一条语句

语法:

if(表达式)                
{                
           语句                
}                
else                
{                
           语句                
}

例子:

#include                
int main()                
{                
           int age = 0;                
           scanf("%d", &age);                
           if (age >= 18)                
           {                
                      printf("已经成年了n");                
                      printf("该上大学了n");                
           }                
           else                
           {                
                      printf("未成年n");                
                      printf("还没上大学n");                
           }                
           return 0;                
}                
               
if esle的本质就是如果没有满足if的表达式那么就直接执行else里面的语句                
               
按照上面的代码逻辑来看,如果我们输入的age值满足if的表达式就打印已经成年了,没有就直接执行else里面的语句                
所以如果你输入的值大于等于18就打印已经成年了,没有就是打印未成年。

3.switch  

switch语句是一个多分支选择语句,并且可以支持嵌套    

语法:

               
switch(表达式)                
{                
case 常量1:语句1                
case 常量2:语句2                
default:语句n                  
    break;                
}

例子:

                 
#define _CRT_SECURE_NO_WARNINGS 1                
#include                
int main()                
{                
    int day = 0;                                              //定义一个整型变量day,并对其赋值为0                
           printf("请输入一个数字n");   //让用户输入一个数字                
           scanf("%d", &day);                                            //接收用户输入的数字                
           switch (day)                
           {                
           case 1:printf("星期一n"); //如果day的值为1,则输出星期一                
           case 2:printf("星期二n");           //以下同上                
           case 3:printf("星期三n");                
           case 4:printf("星期四n");                
           case 5:printf("星期五n");                
           case 6:printf("星期六n");                
           case 7:printf("星期天n");                
           default:                
                      break;                
           }                
    return 0;                
               
我们先观看代码逻辑根据我们输入的值会产生不同分支选择                
               
这里我们接收的变量是day,day会作为switch的表达式,当day = 1那么就会满足第一个分支,就打印星期一以此类推                
如果上面的七个分支都没满足就会走到default这个分支。和if else类似。                

循环函数  

1.while循环语句:  

语法:    

while(表达式)                
{                
    循环语句;                
}

例子:

#include                
               
int main()                
{                
           int n = 1;                
    while (n <= 10)//如果n<=10就继续执行循环的内容                
           {                
                      printf("%d ", n);                   
        n++;//调整循环的部分                
           }                
           return 0;                
}                
               
               
代码的执行结果就是打印从1到10,当n自增到11时就会退出循环,因为已经不满表达式条件了                
n++等同于n = n + 1

2.for循环语句()  

语法:

for(表达式1; 表达式2; 表达式3)                
               
{                
        循环语句;                
}

例子:

int i = 0; //初始化变量                
                 
for (i = 1; i <= 10; i++)//第一个分号之前的为表达式1以此类推分别为表达式2和表达式3                
{                
           printf("%d ", i); //需要循环的语句                
}                
               
这个循环的逻辑是,先给用于进行判断的变量进行赋值,然后根据表达式2的判断语句进行判断,如果i<=10那么就执行循环语句,反之则退出循环,表达式3就是用于给i变量自增,以满足循环能够结束,否则就会无限循环                
               
这段代码的执行结果就是 从1打印到10。    

3.do...while循环  

do while循环与while循环的语法基本差不多,但是do while至少会先执行一次循环语句。

语法:

do                 
{                
    循环语句;                
}while(表达式);

例子:

int i = 1;                
do                 
{                
               
    printf("%d",a)                
    i++;                
}while(i <= 10);                
               
这段代码的逻辑就是,先执行一次打印,然后在进行判断,i是否<=10如果满足表达式就继续执行循环语句,打印2到10。                
               
所以do while和while的区别就是最少会先执行一次循环语句,在判读是否满足表达式。                
               
               
               

                

常规shellcode执行步骤(为核心基础步骤)  

 1.计算shellcode内存大小(因为我们需要去申请一块内存存放我们的shellcode,所以需要获得shellcode的大小)

 2.申请shellcode内存(根据大小申请内存,这里我们需要申请可读可写可执行的内存)

 3.将shellcode写入内存中(写入shellcode)

 4.执行shellcode内容(shellcode放入内存以后我们将它执行起来)

              

                  

原文始发于微信公众号(泾弦安全):免杀对抗从0开始(一)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月24日22:20:07
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   免杀对抗从0开始(一)https://cn-sec.com/archives/3310025.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息