当前位置:   article > 正文

c#的反汇编对抗

c#的反汇编对抗

前记

随便编写一个c#调用winapi并用vs生成dll,同时用csc生成exe

using System;
using System.Runtime.InteropServices;
namespace coleak
{
    class winfun
    {
        [DllImport("User32.dll")]
        public static extern int MessageBox(IntPtr h, string m, string c, uint type);
        [DllImport("kernel32.dll", EntryPoint = "Beep")]
        public static extern bool mymethod(uint frequency, uint duration);
    }
        class Program
    {
            static void Main(string[] args)
            {
            winfun winfun = new winfun();
            winfun.MessageBox((IntPtr)0, "yueyy", "coleak",(uint) 0);
            Random random = new Random();
            for (int i = 0; i < 10000; i++)
            {
                winfun.mymethod((uint)random.Next(10000), 100);
            }
            Console.ReadLine();
            }
    }
}
/*BOOL Beep(
DWORD dwFreq,
DWORD dwDuration
);
int MessageBox(
  [in, optional] HWND hWnd,
  [in, optional] LPCTSTR lpText,
  [in, optional] LPCTSTR lpCaption,
  [in] UINT uType
);*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

优点:隐藏导入表,仅存在mscoree.dll

缺点:在dnspy下均直接出源码

nim攻防基础

为了更加OPSEC,考虑使用nim代替c#核心部分,nim防止反编译同时也不暴露导入函数

FFI

proc MessageBoxA*(hWnd: int, lpText: cstring, 
                  lpCaption: cstring, uType: int32): int32 
                 {.discardable, dynlib: "user32", importc.}
MessageBoxA(0, "Hello, world !", "MessageBox Example", 0)

proc WinExec*(lpCmdLine:cstring,uCmdShow:int32): int32 {.discardable,dynlib:"kernel32",importc.}
WinExec("calc.exe",0)

proc printf(format: cstring): cint {.importc, varargs,discardable.}#discardable忽略返回值否则报错
printf("My name is %s and I am %d years old!\n", "coleak", 20)

proc mycmp(a, b: cstring): cint {.importc: "strcmp", nodecl.} #=proc strcmp(a, b: cstring): cint {.importc, nodecl.}
let cmp = strcmp("Easy!", "Easy!")
echo cmp
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

嵌入c

when not defined(c):
    {.error: "Must be compiled in c mode"}
{.emit: """
#include <stdio.h>
int Test() 
 {
    char name[100]={0};
    scanf("%s",name);
    printf("嵌入成功,%s",name);
    return 0;
 } // end main 
""".}

proc Test(): int
    {.importc: "Test", nodecl,discardable.}
when isMainModule:
    discard Test()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

内存加载

读取字节流

import os
var buf: array[4096,byte]
var f: File
f = open(r"D:\c_project\nim\test.exe")
discard readBytes(f, buf,0,4096)
f.close()
echo buf
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

c.exe>aaa.txt

import winim/clr
import sugar
import os
var buf: array[4096,byte]
buf = [77, 90, ..., 0]
var assembly = load(buf)
var arr = toCLRVariant(commandLineParams(), VT_BSTR)
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

c#虽然没有暴露导入信息,但是在hxd下会暴露字符串信息,因此在 Nim 编译的可执行文件中检测 .NET 程序集仍然很容易,还可以用hxd轻松搜到nim加载的程序集中存在的user32.dll字符信息和exe关键词

在这里插入图片描述

加解密、编码

base64

import base64
import os
import strformat
func toByteSeq*(str: string): seq[byte] {.inline.} =
    # Converts a string to the corresponding byte sequence
    @(str.toOpenArrayByte(0, str.high))
let inFile: string = paramStr(1)
let inFileContents: string = readFile(inFile)
# To load this .NET assembly we need a byte array or sequence
var bytesequence: seq[byte] = toByteSeq(inFileContents)
let encoded = encode(bytesequence)
echo fmt"[*] Encoded: {encoded}"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
import base64
import os
import strformat
import winim/clr
import sugar
import os
func toByteSeq*(str: string): seq[byte] {.inline.} =
    # Converts a string to the corresponding byte sequence
    @(str.toOpenArrayByte(0, str.high))
let encoded = r"TVqQAAMAAAAEAAAA//8...AAA=="
let decoded = decode(encoded)
let mys=toByteSeq(decoded)
var assembly = load(mys)
var arr = toCLRVariant(commandLineParams(), VT_BSTR)
assembly.EntryPoint.Invoke(nil, toCLRVariant([arr]))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

可以换成别的方式加密.NET 程序集,用于运行时解密

后记

C#类型转换表

WindowsC#
BOOLint
BOOLEANbyte
BYTEbyte
UCHARbyte
UINT8byte
CCHARbyte
CHARsbyte
CHARsbyte
INT8sbyte
CSHORTshort
INT16short
SHORTshort
ATOMushort
UINT16ushort
USHORTushort
WORDushort
INTint
INT32int
LONGint
LONG32int
CLONGuint
DWORDuint
DWORD32uint
UINTuint
UINT32uint
ULONGuint
ULONG32uint
INT64long
LARGE_INTEGERlong
LONG64long
LONGLONGlong
QWORDlong
DWORD64ulong
UINT64ulong
ULONG64ulong
ULONGLONGulong
ULARGE_INTEGERulong
HRESULTint
NTSTATUSint

nim基础

语法速记

一、分支允许使用逗号分隔的值列表

let name = readLine(stdin)
case name
of "":
  echo "Poor soul, you lost your name?"
of "name":
  echo "Very funny, your name is name."
of "Dave", "Frank":
  echo "Cool name!"
else:
  echo "Hi, ", name, "!"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

二、of全覆盖

from strutils import parseInt
echo "A number please: "
let n = parseInt(readLine(stdin))
case n
of 0..2, 4..7: echo "The number is in the set: {0, 1, 2, 4, 5, 6, 7}"
of 3, 8: echo "The number is 3 or 8"
else: discard
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

三、迭代器

echo "Counting down from 10 to 1: "
for i in countup(1, 5):
  echo i
for i in countdown(6, 2):
  echo i
for i in 10..19:
    echo i
for i in 1..<19:
    echo i
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

四、块语句

block myblock:
  echo "entering block"
  while true:
    echo "looping"
    break # 跳出循环,但不跳出块
  echo "still in block"

block myblock2:
  echo "entering block"
  while true:
    echo "looping"
    break myblock2 # 跳出块 (和循环)
  echo "still in block"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

五、缩进原则

# 单个赋值语句不需要缩进:
if x: x = false

# 嵌套if语句需要缩进:
if x:
  if y:
    y = false
  else:
    y = true

# 需要缩进, 因为条件后有两个语句:
if x:
  x = false
  y = false
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

六、函数

proc yes(question: string): bool =
  echo question, " (y/n)"
  while true:
    case readLine(stdin)
    of "y", "Y", "yes", "Yes": return true
    of "n", "N", "no", "No": return false
    else: echo "Please be clear: yes or no"

if yes("Should I delete all your important files?"):
  echo "I'm sorry , I'm afraid I can't do that."
else:
  echo "I think you know what the problem is just as well as I do."
  
proc add(a:int,b:int):int=
    return a+b

echo add(1,89)

proc sumTillNegative(x: varargs[int]): int =
  for i in x:
    if i < 0:
      return
    result = result + i

echo sumTillNegative() # echos 0
echo sumTillNegative(3, 4, 5) # echos 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

函数定义格式看起来很繁琐,返回值类型放在: bool =

result 总在过程的结尾自动返回如果退出时没有 return语句

七、传实参

proc divmod(a, b: int; res: var int,remainder:var int) =
  res = a div b        # 整除
  remainder = a mod b  # 整数取模操作

var x, y=111

divmod(8, 5, x, y) # 修改x和y
echo x
echo y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

传递实参用var修饰

八、忽略返回值discard

proc p(x, y: int): int {.discardable.} =
  return x + y

var c:int
c=p(3, 4) # now valid
echo c
p(3, 4)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

九、数组初始化

type
  IntArray = array[0..7, int] # 一个索引为0..7的数组
  QuickArray = array[6, int]  # 一个索引为0..5的数组
var
  x: IntArray
x = [1, 5, 3, 4, 5, 77,9,8]
for i in low(x)..high(x):
  echo x[i]
for i in x:
  echo i
  
for i, v in @[3, 7, 5]:
  echo "index: ", $i, ", value:", $v
# --> index: 0, value:3
# --> index: 1, value:4
# --> index: 2, value:5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

十、结构体

type
  Person = object
    name: string
    age: int

var person1 = Person(name: "Peter", age: 30)

echo person1.name # "Peter"
echo person1.age  # 30

var person2 = person1 # 复制person 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

十一、读写文件

#字节流
import os
var buf: array[100,byte]
var f: File
f = open("D:\\c_project\\nim\\d.exe")
discard readBytes(f, buf,0,9)
f.close()
echo buf


#文本文件
var file:File
file = open(r"D:\c_project\nim\d.txt")
echo file.readAll()
file.close()

let text = "Cats are very cool!"
writeFile("cats.txt", text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

十二、绝对路径默认目录为shell路径

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/86000
推荐阅读
相关标签
  

闽ICP备14008679号