免杀笔记 -- 01

admin 2024年8月23日00:45:15评论30 views字数 3793阅读12分38秒阅读模式

阅读须知

网上找的免杀视频,看着还挺全的,跟着视频过一遍。

本文为笔者看视频1,2,3后所写。仅供参考。

免杀笔记 -- 01

视频1为序章,可以用来做了解,(可看可不看)

后续部分视频是对C语言从免杀的角度进行的讲解,有C基础的可以高倍速的过一遍,无基础的不能只看视频,要结合菜鸟教程,gpt,和一些其他资料(比如本系列)来看

视频2主要是讲变量、数组、函数、命令行传参、循环、结构体

视频3讲了指针,和经典的二阶指针、函数指针、数组指针和指针数组的区别。(这就不多介绍了,网上大把优秀的讲解,肯定比我写的好)

值得说的是:命令行传参

int main(int argc,char *argv[])argc:命令行参数的个数,也就是argv的个数,默认为1argv:命令行参数的数组,argv[0],代表第一个字符串参数的地址

在C或C++程序中,main函数是程序的入口点,即程序执行时首先调用的函数。main 函数的参数允许程序接收来自命令行或终端的参数。

函数原型 int main(int argc, char *argv[]) 是这些用法中非常常见的一种,下面是对其详细解释:

参数解释

int argc:这是一个整型变量,代表命令行参数的数量。

argc 至少为1,因为第一个参数(argv[0])总是程序的名称或路径。如果用户还输入了其他参数,那么 argc 的值会相应增加。

char *argv[] 或等价的 char **argv:这是一个字符指针数组(或指向字符指针的指针),用于存储命令行参数的字符串表示。

每个元素都是一个指向以 null 结尾的字符数组(即C字符串)的指针。

argv[0] 是程序的名称或路径,argv[1] 是第一个用户指定的参数,依此类推,直到 argv[argc-1],它是最后一个参数。注意,argv[argc] 是 NULL(或等价的,在C++中为 nullptr),用来表示数组的结束。

示例

假设有一个名为 example 的程序,你在命令行中这样调用它:

bash
./example arg1 arg2 arg3

 


在这个例子中:

argc 的值是 4,因为有四个参数:
程序名 example 和三个用户提供的参数 arg1、arg2、arg3。
argv[0] 指向包含 "example" 的字符串。argv[1] 指向包含 "arg1" 的字符串。argv[2] 指向包含 "arg2" 的字符串。argv[3] 指向包含 "arg3" 的字符串。argv[4] 是 NULL

 

分割线

------------------------------------------------------------------------

视频2作业

免杀笔记 -- 01

作业一:写一个字符串数组能输出字符串,但是在二进制文件中搜索不到该字符串(不通过加密)

主要实现方式就是:通过将字符串改为一个一个字符进行输出。比如:printf("glassn");替换为char g[] = {'g','l','a','s','s',0};printf("%sn",g);

使用WinHex进行查看exe文件。

替换前:

免杀笔记 -- 01

替换后:

免杀笔记 -- 01

在选择解决方案配置中,要选择“Dubug”,而不是“Release”,因为“Release”会对程序进行一定程度的优化(从两个文件的大小中也可以看到),即有可能会被搜到。

免杀笔记 -- 01

作业二:解析字符串的单词的个数,如“Happiness is about having each tiny wish come ture.”

#include <iostream>// 函数声明  int countWords(const char* str);
int main() {    const char* sentence = "Happiness is about having each tiny wish come true ";    int wordCount = countWords(sentence);    printf("字符串的单词的个数为: %dn", wordCount);    return 0;}// 函数定义  
int countWords(const char* str) {    int count = 0; // 初始化单词计数器      bool inWord = false; // 标记当前是否在单词中      // 遍历字符串直到遇到空字符'�'      while (*str != '�') {        // 如果当前字符不是空格且之前不在单词中,则进入一个新单词          if (*str != ' ' && !inWord) {            inWord = true;            count++;        }        // 如果当前字符是空格且之前已在单词中,则退出单词          else if (*str == ' ' && inWord) {            inWord = false;        }        // 移动到下一个字符          str++;    }    // 注意:如果字符串以单词结束(即没有尾随空格),则最后一个单词也会被计数      // 上面的逻辑已经处理了这种情况,因为我们在进入新单词时增加了计数,而无需检查后面的字符    return count;}

作业三:以上两个功能都用函数实现,主函数来调用

这个直接把作业一包装成一个函数即可。

void printfg() {    char g[] = { 'g','l','a','s','s',0 };    printf("%sn", g);}
int main() {
    const char* sentence = "Happiness is about having each tiny wish come true ";    int wordCount = countWords(sentence);    printf("Number of words: %dn", wordCount);    printfg();    return 0;}

作业四:单独写一个程序尝试加密你作业程序的所有字符串,加密的话就选择异或(可选)

#include <iostream>  
// 异或加密函数(保持不变)  
void xor_encrypt(const char* plaintext, char* ciphertext, const char* key) {    int key_len = strlen(key);    int i = 0;    while (*plaintext) {        *ciphertext = *plaintext ^ key[i % key_len];        plaintext++;        ciphertext++;        i++;    }    *ciphertext = '�';}
int main() {    // 待加密的字符串      const char* str1 = "glass";    const char* str2 = "Happiness is about having each tiny wish come true.";    // 密钥      const char* key = "123456789";    // 分配内存给加密后的字符串(包括终止符'�')      void* encrypted1 = malloc(strlen(str1) + 1);    char* encrypted11 = (char*)encrypted1;//强转    void* encrypted2 = malloc(strlen(str2) + 1);    char* encrypted22 = (char*)encrypted2;
    if (encrypted1 == NULL || encrypted2 == NULL) {        fprintf(stderr, "Memory allocation failedn");        return 1;    }    // 加密字符串      xor_encrypt(str1, encrypted11, key);    xor_encrypt(str2, encrypted22, key);    // 输出加密后的字符串      printf("Encrypted '%s': %sn", str1, encrypted11);    printf("Encrypted '%s': %sn", str2, encrypted22);    // 释放分配的内存(使用原始的void*指针)      free(encrypted1);    free(encrypted2);    return 0;}

异或加密函数 xor_encrypt

这个函数实现了简单的异或加密。它接受三个参数:一个指向明文(plaintext)的指针、一个指向密文(ciphertext)的指针,以及一个指向密钥(key)的指针。函数通过逐字节地对明文和密钥进行异或操作来生成密文。密钥是循环使用的,这意味着如果密钥的长度小于明文的长度,那么密钥会从头开始重复使用。

·key_len 存储了密钥的长度。

·使用 while 循环遍历明文中的每个字符,直到遇到空字符('�'),表示字符串的结束。

·在循环内部,使用异或操作符 ^ 对当前明文字符和密钥中的对应字符(通过 i % key_len 实现循环)进行异或操作,结果存储在密文的相应位置。

·然后,移动明文和密文的指针到下一个字符,并增加 i 以跟踪密钥中当前使用的字符位置。

·循环结束后,在密文的末尾添加一个空字符 '�' 以确保它是一个有效的C字符串。

main 函数

·定义了两个待加密的字符串 str1  str2,以及一个密钥 key

·为每个待加密的字符串分配了足够的内存来存储加密后的字符串(包括空字符)。这里使用了 malloc 函数,并将返回的 void* 指针转换为 char* 指针以便操作。

·检查内存分配是否成功。如果任一内存分配失败(即 malloc 返回 NULL),则打印错误信息并返回 1

免杀笔记 -- 01

异或加密是对称加密。可以直接二次输入解密。

免杀笔记 -- 01

这是视频1,2,3的笔记。后续会持续更新。

原文始发于微信公众号(Glass的网安笔记):免杀笔记 -- 01

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

发表评论

匿名网友 填写信息