- 博客(3116)
- 资源 (44)
- 收藏
- 关注
原创 Mono里运行C#脚本16—mono_image_load_metadata
在程序集中,这样的关联是单向的——为了找到哪种类型拥有特定的方法,您必须扫描TypeDef表,直到找到一个在其方法列表中包含该方法的类型。tiny格式的方法,一般是使用来描述属性方法的定义,比如获取和设置方法,还有一些只是加载一个字段,或者加载一个参数存储等等。例如,ldarg指令(加载参数)是一个2字节的指令,它接受一个2字节的参数,其中包含要加载的参数编号。需要仔细地查看方法的标记编码,在这个例子里,指出这个方法没有参数,并使用一个void的返回类型。0x72 是一个操作码,表示ldstr指令。
2025-01-01 02:10:02
357
原创 Mono里运行C#脚本15—mono_image_load_metadata
后面一个函数是加载"#~" 或 "#-"流里的逻辑表示数据。这里通过前面CLI头部来获取到meta数据的相对位置cli_cli_header.ch_metadata.rva,接着转换为绝对位置,这样能从后面位置里获取到数据。前面已经分析了加载CLI头部分的内容,接着下来,就是调用mono_image_load_metadata函数来加载metadata的数据内容了。这里是读取"#-"数据流开始位置和长度,与前面"#~"的区别,它是压缩方式。这里是读取"#GUID"的数据流开始位置和长度。
2024-12-31 23:58:35
203
原创 Mono里运行C#脚本14—.net CLR metadata
每一位表示不同索引值的大小,比如第一位0x01表示#Strings流中索引大小为4个字节大小,如果是0x00表示索引大小为2个字节,其它依次类推。0x0000000900001447表示存在表 0, 1, 2, 6, 10, 12, 32, 和 35。“#~” 流表示表的集合。最基本的有5种流,每种类型最多只出现一次,比如不可能出现两个“#US”流,五个“#Blob”流。4 4 表示本流的长度,单位为字节,应该是4的倍数。读取出现的表的长度字节之后,就是每个表索引的起始位置。
2024-12-30 15:56:44
382
原创 Mono里运行C#脚本13—mono_image_load_cli_header
也就是pe_image_match和pe_image_load_pe_data函数,一个是判断是否匹配PE文件格式,一个是加载PE文件头的信息,它是为了获取后面的信息为铺垫。由于虚拟地址是加载到内存运行的地址,与文件保存在磁盘里的地址不一样,这里是使用文件加载的,所以需要使用文件地址来访问。而在这里加载头部数据,需要根据前面的头部目录项里找到相对地址,再根据段表里找到段的开始地址,才能计算出来相对文件开始位置地址。也就是说这段在文件里的开始位置为512字节的位置,不是执行时加载的虚拟地址8192。
2024-12-29 11:34:50
283
原创 Mono里运行C#脚本12—load_section_tables
通过上面的分析,我们就可以理解段头是怎么样加载到内存,并且找到段的开始位置和描述内容。里定义的内容太简单了,只有8个字节一项,只能说明每一段的开始位置和大小,并没有这段的属性,那么只能在后增加一头来描述这段的属性了。st_virtual_address RVA)节在内存中的偏移地址.加上ImageBase才是在内存中的地址.st_raw_data_size 节在文件中按照文件对齐后的大小.st_raw_data_ptr (FOA)节在文件中的偏移地址.st_lineno_ptr 行号表的偏移,提供调试.
2024-12-29 10:28:03
337
原创 Mono里运行C#脚本11—do_load_header_internal
前面分析了EXE文件的PE格式,接着下来我们就来仔细地分析怎么样加载PE格式的文件,它主要通过加载器来配置,然后调用合适的加载器来处理的,下面就是加载器里的四个函数,只需要把这四个函数搞清楚,就可以把整个文件加载的过程可以搞明白,这样后面就可以明白虚拟机所需要的数据来源,也是CLI内容信息。,它分为两个格式,第一个格式是MonoPEHeaderNT,对应是PE32的文件格式,第二个格式是MonoPEHeaderNT64,对应是PE64的文件格式。眼尖的你,也许会发现倒数第二个字段是一个CLI头的入口。
2024-12-28 19:11:13
177
原创 Mono里运行C#脚本10—do_mono_image_load
在这里先定义一个加载的数据结构MonoImageLoader对象,然后再把这个对象设置到前面的链表里,也就是说后面所有调用加载的函数,就是这里定义的函数,所以我们分析这些函数的实现,就明白怎么样来加载EXE文件的。前面分析do_mono_image_open函数,它负责把文件打开,并保存在HASH表里,然后设置映像对象的数据,接着下来就是解释文件里面的内容,即是EXE文件的内容了。后再来分析这个加载器的具体内容。前面那个是所有EXE文件的格式,后面这个是C#文件编译出来的EXE的格式。
2024-12-28 13:22:51
662
原创 Mono里运行C#脚本9—do_mono_image_open
因为调用mono_image_storage_open 函数是在do_mono_image_open函数完成的,因此我们来分析do_mono_image_open函数。这里就是调用打开文件,并保存到HASH表里的函数。最后就是进行加载整个文件,主要就是解释里面的内容,比如验证DOS头/PE头等等。前面介绍怎么样打开文件,并保存文件到HASH表里,如果没有可以访问文件数据的指针,就当作出错并返回。设置文件加载的内存指针,以便可以访问文件数据。如果没有打开文件成功,就当作失败直接返回。这两个都是保存文件路径。
2024-12-28 01:13:22
242
原创 Mono里运行C#脚本8—mono_image_storage_open打开EXE文件
/对文件路径名称进行合法化转换,然后使用它作为HASH表里键,打开的文件对象就是值,键值对为(文件路径, 文件对象)。//调用函数mono_image_storage_trypublish把文件对象保存到HASH表,如果保存失败就删除。//调用函数mono_file_map_open来打开文件,保存在句柄filed,如果打开失败就返回。//通过键来查看此文件是否存在HASH表,如果存在,就增加此对象的引用计数,并且返回文件对象。//打开文件,并把文件映射地址保存在这里,后面可以通过里访问数据。
2024-12-27 15:43:29
219
原创 Mono里运行C#脚本7—MonoImageStorage结构解析
这段代码实现了一个路径检查化函数 mono_path_canonicalize,用于解析路径中包含 .. 和 . 字符时进行合适转换,以便转换为绝对路径。//是否使用mono_file_map函数打开。//是否有_CorDllMain入口点。这段代码的主要目的是将给定的路径合理转换,使文件路径中不包含 . 和 .. 字符,并确保路径格式正确。遍历路径中的每个段(以 G_DIR_SEPARATOR 分隔)。//HASH的键,通过键可以快速访问。
2024-12-27 14:24:01
265
原创 Mono里运行C#脚本6—mono加载EXE文件和DLL文件保存的HASH表
遍历:可以使用 g_hash_table_iter_init() 和 g_hash_table_iter_next() 函数来遍历哈希表中的所有键值对。创建:使用 g_hash_table_new() 函数创建一个新的哈希表,需要提供键和值的哈希函数以及键和值的比较函数。在这里创建一个HASH表对象,也是分配内存,并且使用g_str_hash和g_str_equal作为HASH计算的函数。通过上面的函数定义,就可以实现一个保存EXE文件和相关DLL文件的存储HASH表,以便快速地访问所有相关的文件数据。
2024-12-27 10:52:45
447
原创 Mono里运行C#脚本5—mono_file_map_open
Mono要运行exe文件,这里是运行test-embed.exe文件,那么就得认识这个文件,解释这个文件的内容,因此就需要把这个文件加载到内存里,然后采用特定的格式来分解这个文件,获得所有需要运行这个文件的细节。这段代码定义了一个名为 mono_file_map_open 的函数,用于打开一个文件并返回一个文件映射对象 MonoFileMap*。该函数根据操作系统平台的不同,使用不同的方法来打开文件。因此改变另外一种方式,先从底层的函数开始,再慢慢来探索mono的底层实现,以及它的实现原理,运行的细节。
2024-12-26 22:58:44
339
原创 Mono里运行C#脚本4—mono_mutex_t 锁的实现
linux下的互斥量pthread_mutex_t是非递归锁,但是可以通过在创建互斥量时设置PTHREAD_MUTEX_RECURSIVE属性,将pthread_mutex_t设置为递归锁。• 解锁:线程在完成对共享资源的访问后,需要通过 pthread_mutex_unlock 函数释放互斥锁,以便其他线程可以获取锁并访问资源。递归锁:同一个线程在不解锁的情况下,可以多次获取锁定同一个递归锁,而且不会产生死锁;非递归锁:在不解锁的情况下,当同一个线程多次获取同一个递归锁时,会产生死锁。
2024-12-26 09:59:16
278
原创 Mono里运行C#脚本3—mono_jit_init
为什么这样说呢,因为需要解释并执行C#编译的受托管的代码,相当于就是建立一个C#代码运行的虚拟机,而这个虚拟机还是很复杂的,不但要支持C#运行各种特性,比如内存管理的垃圾回收机制,还需要对C#的代码进行即时编译,或者提前编译AOT,并且可以根据不同的平台生成不同的代码,比如在X64上生成的代码,与ARM64上生成的代码就会不一样,执行的速度也不一样,处理的方式也不一样。前面已经介绍了配置参数的读取,这样就可以把一些特殊的配置读取进来,完成了用户配置阶段的参数,接着下来就需要进行大工程的建造了。
2024-12-24 22:29:03
289
原创 Mono里运行C#脚本2—参数配置
在这里定义一个内存虚拟表变量mem_vtable,包括内存表的版本,内存管理的函数指令设置,这里设置为custom_malloc,这个函数就是本程序里的一个简单函数,如果你忘记了应该去查看一下前面的代码。在这里定义一个内存分配映射的方法,因为不同的平台运行C#时,需要使用不同的内存管理方法,因此定义一个接口,只要改变这个接口,就可以使用不同的内存管理。这段代码根据输入的文件名称参数判断,如果文件名称为空,就说明不指定配置文件,如果不为空就加载这个指定的配置文件。就会调用上面的函数去读取指定的配置文件。
2024-12-22 12:03:18
221
原创 Mono里运行C#脚本1
这段代码,就是内部定义了一个命令行参数,第一个参数是本程序的名称,第二个参数是将要运行C#生成的目标代码,也就是前文中的汇编代码:test-embed.exe。前面已经知道怎么样把C#的源码通过MCS编译器生成exe的文件,然后我们还把 exe的文件进行反汇编查看,知道我们需要处理的目标,就是这些汇编的代码。这些库的版本,要与编译C#的代码一样,否则运行会出错。这段代码为了简单演示嵌入脚本的功能,没有进行命令行参数的方式来传递处理的文件,而是使用程序内部固定参数的方法,所以没有传入命令行参数。
2024-12-22 10:30:06
335
原创 Mono里建立调试C#脚本运行环境
接着后面就是定义一个入口点函数Main (),它是C#程序的定义的要求,以便从众多的代码里,找到一个执行这一堆代码的开始地方。这是我们写C#程序的基本格式,也是定义程序开始位置的要求。在这里说明了这个函数是声明在C程序内部的,意味着C#程序脚本是可以调用C语言内部的功能,从而达到脚本控制宿主的功能。如果底层的代码提供堆的功能,就可以像这样提供很多函数的接口,就可以支持完美的功能了。通过上面的命令行,就会输出test-embed.exe程序,后面我们就们会打开这个程序来运行它。上面脚本就是调用此函数。
2024-12-21 22:24:58
198
原创 C# 最简单的例子:Mono嵌入脚本
应用程序域(Application Domain)是.NET Framework中的一个重要概念,它是一个隔离的执行环境,用于在一个进程中运行多个独立的应用程序。隔离性:每个应用程序域都是相互隔离的,一个应用程序域中的异常不会影响其他应用程序域的运行。其实,都可以参考mono的实现方式,或者直接借鉴mono的代码,然后就可以放到自己的软件系统里了。安全性:应用程序域可以通过配置文件进行安全策略的设置,限制代码的权限,从而提高应用程序的安全性。• 提供了一个简单的示例,展示了如何加载和执行C#程序集。
2024-12-21 16:05:45
567
原创 在Windows11上编译C#的实现Mono的步骤
export MONO_EXECUTABLE=/cygdrive/c/源码路径/msvc/build/sgen/x64/bin/Release/mono-sgen.exe。3、 安装 Visual Studio 2015 or later 的社区版本。2、下载并安装64位的cygwin, 下载网站:www.cygwin.com。export PREFIX=[mono安装位置]4、 下载Mono的windows最新版本。在Windows11上编译Mono的步骤。9、用VS2022编译mono.sln工程。
2024-12-21 13:27:56
306
原创 C#里怎么样实现调用7z来快速地压缩文件和解压文件?
根据代码,SevenZip 类封装了对 7-Zip 命令行工具的基本操作,包括压缩多个文件、压缩目录、解压文件以及无目录结构解压文件。• DecompressNoDir: 解压指定的 7z 文件到目标目录,但不保留原目录结构,即所有文件直接解压到目标目录下。又或者想把文件保存在数据库里,这时需要把文件压缩一下,再保存到数据库,这样就可以减少数据库占用的空间。由于7z是开源的软件,又是表现得非常优秀,采用它来压缩的文件会比较小,速度也比较快。在处理数据时,经常会遇到文件占用磁盘空间比较大的问题,
2024-12-19 11:09:50
213
原创 C#里怎么样删除字典里多项元素?
如果采用字典,就可以快速地通过字典键来查询到对象,其实这个时间就是HASH表的操作时间。因此,我们需要采用另外的访问,就是把字典的键先抽取出来,然后再遍历,就完善解决了。采用字典时,我们有时候需要同时删除多个元素对象,比如刚除多个IP地址断掉的连接。比如一个服务器,有多个TCP连接上来,每次要通过IP地址来访问这些连接对象,当我们使用字典比较多的情况,一般来说,就是为了提高查询的速度。在这里先把字典的键抽取出来,再遍历删除键为2、4两个元素。如果采用列表来保存,就只能遍历来查询到连接对象。
2024-12-15 12:03:54
269
原创 在Macbook m4上编译mono出错:error: incompatible pointer to integer conversion assigning to ‘__uint64_t‘
由于想理解一下C#的底层实现,同时也想看一下游戏引擎里使用脚本Mono,按这样个性之后,就可以正确运行了。因为m4是64位的ARM了。所以今天就去mono的github上下载了一个源码,这里要根据自己的目录来定义:PREFIX。
2024-12-14 12:40:34
212
原创 C#里怎么样使用where方法2?
为了组合其它LINQ方法: 因为Where方法可以组合其它LINQ方法, 比如Select, OrderBy, GroupBy, 等等,这样可以构成更复的查询场合。使用内存容器并且符合IQueryable的数据源:可以使用在容器List 和 Array等容器上,或者定义了IQueryable接口的数据源,比如数据集.不过,如果是在有序的队列里,去找某个元素,最好是使用二分查找法,它们比前面三种方式都会快得多。将在谓词函数的逻辑中使用每个元素的索引。在开发里,如果在无序的队列里,要找到某类元素,
2024-12-07 12:39:37
459
原创 C#里怎么样使用where方法?
不过,如果是在有序的队列里,去找某个元素,最好是使用二分查找法,它们比前面三种方式都会快得多。往往需要循环地遍历所有元素,然后判断这个元素是否符合所需要的条件。在C#里提供了LINQ和where方法,就可以有另外两种选择了。基于谓词筛选值序列。将在谓词函数的逻辑中使用每个元素的索引。在开发里,如果在无序的队列里,要找到某类元素,这个方法,就是前面使用的方法,不使用索引下标。这里也是查找所有大于5的元素返回。C#里怎么样使用where方法?这里是查找所有大于5的元素返回。基于谓词筛选值序列。
2024-12-07 12:07:58
781
原创 C#里怎么样快速写出一个快速排序?
但是在大学里,就会不一样,因为需要学习它的原理,或者要写嵌入式的系统,这时候就需要自己写它的算法了。因为很多东西处理,都需要有时序性,比如从网络接收到的数据,当然,在C#的开发库里,已经准备好了我们所需要的排序容器,又或者对于用户输入的数据,都会有排序的需求。在开发里,使用到排序的算法,还是比较多的。C#里怎么样快速写出一个快速排序?所以大家一般很少去写排序算法。
2024-12-06 23:00:31
276
原创 C#里怎么样快速判断一个数是否为2多少次方的数?
这里num是要判断的数,-num是num的负数,即补码,然后进行与运算,最后判断是否等于原来的数。那么所有内存分配,以及磁盘分配,都是按2的多少次方的大小来分配的,在开发里,经常会遇到需要计算判断一个数是否为2的多少方的数,所以怎么样快速判断一个数是否为2的多少次方,就比较有意义了。C#里怎么样快速判断一个数是否为2多少次方的数?这样就会让计算机运算的效率达到最好的水平。因为计算机是按二进制来设计的,
2024-11-30 17:09:52
260
原创 C#里怎么样使用new修饰符来让类智能选择基类函数还是派生类函数?
如果使用一个new修饰符,就会导致它会根据变量的类型而选择不同的函数运行。C#里怎么样使用new修饰符来让类智能选择基类函数还是派生类函数?在C#里有一个特殊的用法,就是在创建与基类相同的函数时,这是一个比较特殊的使用方法,一般情况下,不建议这样使用。这行代码的运行输出。
2024-11-30 16:48:07
327
原创 C#里怎么样使用抽象Abstract定义的属性?
提供的C#代码定义了一个抽象类 Shape 和三个继承自 Shape 的具体类:Square(正方形)、Circle(圆形)和 Rectangle(矩形)。此外,还有一个 TestClass 类,其中的 Main 方法创建了不同形状的实例,并将它们存储在一个 Shape 数组中,最后遍历数组并输出每个形状的 ID 和面积。• 定义了一个抽象属性 Area,要求所有继承自 Shape 的子类必须实现这个属性。• 创建了一个 Shape 数组,包含一个正方形、一个圆形和一个矩形的实例。
2024-11-30 16:37:12
500
原创 C#里怎么样使用Array.BinarySearch函数?
C#里怎么样使用Array.BinarySearch函数?但是它的返回值,也有三种状态,导致很多人使用它的时候,因为二分算法如此重要,所以要多加练习。
2024-11-30 16:24:02
590
原创 C#里怎么样List类进行拷贝?
然后,它将这个列表转换为一个对象数组 objectArray 和一个字符串数组 stringArray。• objectArray 和 stringArray 都包含相同的字符串元素,因为它们都是从同一个列表 list 转换而来的。• "Typed array" 实际上与 "Object array" 是相同的,因为它们都引用了 objectArray。• 创建一个新的字符串数组 stringArray,其长度与列表中的元素数量相同。• 输出 stringArray 的内容。
2024-11-30 15:55:36
525
原创 C#里怎么样创建对象之后,就可以立即调用函数?
在开发里,常常遇到C#里不需要赋值给变量,就可以直接new之后,就可以使用类的方法。这里类GeneratePowers,构造之后直接调用方法RaiseToPower。C#里怎么样创建对象之后,就可以立即调用函数?这里并没有赋值给任何变量。
2024-11-30 14:44:48
262
原创 C#里怎么样LINQ来从数组里获得大于某数的值?
这里使用了from...in ....where ....select语句来实现。其中的分类,就包含找到满足比某个值大的数,然后再对这些数进行处理。如果不使用LINQ,就需要使用循环来遍历所有元素,再来进行判断。当很多很多这样的算法组合起来,就形成了功能复杂的程序。在这里演示使用LINQ来实现获得大于某个数的所有元素。在开发里,很多情况就是获取一些数据进行分类和处理。C#里怎么样LINQ来从数组里获得大于某数的值?这样的任务,就叫做算法。
2024-11-30 14:30:39
534
原创 C#里怎么样使用继承实现不同的功能,以及调用基类函数?
base 关键字在 C# 中用于在派生类中访问基类的成员(字段、方法、属性等)。在派生类中调用基类的成员函数(当你需要在派生类中调用基类的方法,而该方法被重写时)。C#里怎么样使用继承实现不同的功能,以及调用基类函数?访问基类被隐藏的成员(当基类和派生类有同名成员时)。调用基类的构造函数(在派生类构造函数中)。在C#中,经常需要调用基类相同的函数,这时候要使用base对象来访问基类。
2024-11-24 22:07:25
288
原创 C#里怎么样使用LINQ的let关键字实现查询?
在这个例子中,let totalMarks = objStudent.Sum(mark => mark.Marks)声明了一个totalMarks变量,它保存了每个名字的长度。在C#中,let关键字是用来在查询表达式中声明一个范围变量的。范围变量是在迭代过程中保存查询产生的序列中的元素的临时变量。最后,在select子句中,我们选择了所有满足的成员。C#里怎么样使用LINQ的let关键字实现查询?
2024-11-24 21:30:16
284
原创 C#里怎么样快速使用LINQ实现查询?
曾经对100万的数据进行查找,二分法查找就会比较快,使用Where查找,就慢上很多。因为LINQ对数据的访问,并没有优化的功能,往往速度很慢,比特定的算法慢很多。不过,要学会使用这部分的功能,需要比较多的学习时间,否则,使用起就比较难。如果数据量比较大,又有排好序的,这时候就不要一味地使用LINQ,当数据量比较小,没有特定的顺序时,使用LINQ访问会比较好。因为它的表现方式,与编程语言通用的功能,还是差别比较大。比如使用二分法查找,就比Where快N个数量级。在C#里使用LINQ,是一个方便的功能,
2024-11-24 21:23:28
255
原创 C#里怎么样实现多播委托?
如果你想实现一次通知,就可以让多个地方同步执行,在这里使用委托来实现多播的功能。C#里怎么样实现多播委托?这时候就可以使用多播。先定义一个委托的形式。
2024-11-24 16:57:05
740
原创 C#里怎么样使用多线程读取多文件?
多线程在读取文件过程中,可能不存在读取快的优势,不过可以把工作分时进行,不影响界面的工作。要注意两个线程的同步,都需要两个线程结束之后,才能进行文件内容的操作。C#里怎么样使用多线程读取多文件?这里主要比较两个文件是否一样的。每个线程分别读取一个文件,这段代码要注意进行同步。在这里演示两个线程,
2024-11-24 16:39:21
307
原创 C#里怎么样使用正则表达式?
正则表达式是由普通字符(如英文字母)以及特殊字符(也称为元字符)组成的一种文字模式。在C#里要使用System.Text.RegularExpressions。所以,正则表达式可以是单个字符,也可以是更复杂的模式。C#里怎么样使用正则表达式?也可以进行字符串的替换和提取。输入的用户名是否满足条件等。输入的身份证号码是否合法。验证输入的邮箱是否合法。
2024-11-24 13:08:53
368
原创 C#里怎么样实现单向链表?
在软件开发中,使用到的链表还是比较多的。不过,目前C#语言,基本上都类库,所以需要自己创建链表的机会,基本不存在了。不同的数据结构,就需要采用不同的算法。但是作为理解原理,还是学习一下吧。数据结构,是程序基本表示方法。C#里怎么样实现单向链表?
2024-11-24 13:01:51
293
tinyxml2配套源码
2016-06-27
国产8051模拟器
2016-09-10
python抓取天气并分析 实例源码
2017-08-28
胶囊模型的代码
2018-02-02
书《深度学习》
2017-03-13
开源鸿蒙4.0不能进入桌面的补丁
2024-03-17
开源鸿蒙 4.0 RK3566开发板配置
2024-03-17
实现numpy的C++库扩展
2019-11-24
svm_hog_data.rar
2020-03-02
python web py入门配套源代码
2018-02-23
webpy演示例子1
2018-02-21
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人