【问题标题】:Pipe hex into sed and append its output to a file将十六进制管道传输到 sed 并将其输出附加到文件
【发布时间】:2023-04-01 09:03:01
【问题描述】:

我正在尝试编写一个脚本,该脚本获取目标文件的十六进制字符,然后将输出(在 ascii 中)重定向到文件中的特定行。

基本上是这样的

export FILE=myobj_file
export j=''
for b in $(objdump -d -M intel $FILE | grep "^ " | cut -f2); do j+='\x'$b; done; echo $j

这会打印出十六进制代码(shellcode):

\xeb\x0d\x5e\x31\xc9\x67\x2a\x42\x4b\x55\x55\x55\x85\xc8\xc3\xc4\x85\xd9\xc2\xeb\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9

我想将其写入包含以下内容的文件:

#include <stdio.h>
#include <string.h>

int main() { 
unsigned char code[] = {{PLACEHOLDER}} /*Here need to be inserted*/
printf("Length:  %d\n", strlen(code));

    int (*ret)() = (int(*)())code;
    ret();
    return 0;


}

我尝试将输出传递给 sed:

sed '6s/%d/$j/' file.c

但我得到一个错误。

我的结果应该是:

#include <stdio.h>
#include <string.h>

int main() { 
unsigned char code[] = \
"\xeb\x0d\x5e\x31\xc9\x67\x2a\x42\x4b\x55\x55\x55\x85\xc8\xc3\xc4\x85\xd9\xc2\xeb\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9";
printf("Length:  %d\n", strlen(code));

    int (*ret)() = (int(*)())code;
    ret();
    return 0;


}

要么我得到一个 sed 错误,要么我得到 sed 插入 HEX 代码而不是 ASCII,通过将 \x41 转换为 'A',而不是插入 \x41。

谢谢

【问题讨论】:

    标签: bash sed hex pipe ascii


    【解决方案1】:

    hek2mgl的回答类似,我们使用带有占位符的模板文件(此处相同):

    /* ... */
    
    int main() { 
        unsigned char code[] = "{{PLACEHOLDER}}"
        printf("Length:  %d\n", strlen(code));
        int (*ret)() = (int(*)())code;
        ret();
        return 0;
    }
    
    /* ... */
    

    所以现在我们可以将{{PLACEHOLDER}} 替换为:

     awk 'BEGIN{FS="\t"}
          (NR==FNR) && /^ /{
             sub(" +$","",$2);gsub(" ","\\x",$2); string=string "\\x" $2
             next;
          }
          (NR == FNR) { next }
          /{{PLACEHOLDER}}/{ sub("{{PLACEHOLDER}}",string ) }
          1' <(objdump -d -M intel $FILE) code.c > updated_output.c
    

    【讨论】:

    • 好答案!使用这种 awk-only 解决方案,您可以避免 sed argument list too long 错误。并且很容易将其更改为编写可编译的 c 代码。
    • 需要一个小修复 (@lewicz)
    【解决方案2】:

    我最终得到了这个:

    export j=''
    for b in $(objdump -d -M intel /bin/ls | grep "^ " | cut -f2); do j+='\\x'$b; done; echo $j
    sed "s/{{PLACEHOLDER}}/${j}/" file.c
    

    【讨论】:

      【解决方案3】:

      我会在 c 文件中使用占位符:

      /* ... */
      
      int main() { 
          unsigned char code[] = "{{PLACEHOLDER}}"
          printf("Length:  %d\n", strlen(code));
          int (*ret)() = (int(*)())code;
          ret();
          return 0;
      }
      
      /* ... */
      

      然后使用两步法(以 /bin/ls 为例):

      string="$(objdump -d -M intel /bin/ls | awk -F'\t' '/^ /{gsub(/^|\y \y/, "\\\\x", $2);gsub(/ /,"",$2);printf "%s", $2}')"
      sed "s/{{PLACEHOLDER}}/${string}/" file.c
      

      【讨论】:

      • @kvantour 我明白你的意思。但这与问题的输入并不真正匹配。
      • @lewicz 好的。让我知道是否有问题(这意味着我误解了问题)
      • @hek2mgl 谢谢。现在它正在插入十六进制而不是 ascii: unsigned char code[] = "x xxxxxxxxxxxxxxxxxx
      • 我以为你想要十六进制。顺便说一句,根据输出的大小,当${string} 变得太大时,整个事情可能会因argument list too long error 而失败
      【解决方案4】:

      一般来说,我建议您将这个问题更多地视为“模板”而不是“替换”。也就是说,将您的文件从file.c 重命名为file.c.template。然后将标记放入您要修改的模板中。例如:

      #include <stdio.h>
      #include <string.h>
      
      int main() { 
      unsigned char code[] = \
      <% code_hex_string %>
      printf("Length:  %d\n", strlen(code));
      
          int (*ret)() = (int(*)())code;
          ret();
          return 0;
      
      
      }
      

      现在您的所有sed 只需将&lt;% code_hex_string %&gt; 替换为实际的十六进制字符串,就完成了。

      sed -e 's/<%\s*code_hex_string\s*%>/'"$j"'/' < file.c.template > file.c
      

      一旦你有了这个概念,它也能很好地翻译成其他语言,你可以很容易地将你的 bash 脚本扩展成 perl/python/groovy/C#/任何东西。

      【讨论】:

      • 好吧,我试过了,问题是它插入的是十六进制代码而不是 ASCII 作为十六进制代码: unsigned char code[] ="1��1۳1�Rho �hHell��1Ҳ̀1�� 1�̀"
      猜你喜欢
      • 1970-01-01
      • 2016-01-10
      • 2013-11-11
      • 2017-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多