很多准爸妈们都会对自己还未出生的宝宝性别感到很好奇,而国家是有严令禁止孕期查看胎儿性别的规定的,那么我们可能会根据老人们讲的肚子形状,或者孕期反应,饮食偏好等症状来猜测自己宝宝的性别,准爸妈们玩笑之余却又倍感期待。随着现在科技的发达,孕妈妈们在孕期也会相对的做一些检查,其中就有一项——NT三维彩超检查,那么,通过NT的检查数据真的能看出是男宝宝还是女宝宝么?
NT检查是孕早期一个比较重大的一项检查,通过各方面的数据会对孕宝宝的健康情况做出一个衡量。那么,大家有没有注意呢,彩超单上有一栏写着SEX的检查项目,大家都知道SEX是“性别”的意思,以我老婆蛋宝的检查单为例,后面的英文单词为“female”,也就是女性的意思,难道这就是胎宝宝的性别么?(这里给大家放上我老婆检查的单子,如下图:)
之后,我上网搜查了一些这方面的内容,答案也不尽然,有说是孕妈妈的性别(这不废话么!),也有一些是其他答案的。(孕妈妈们可以在评论里晒一下自己的NT单子,一起讨论下。)我也专门问了一下医生,医生只是笑了笑什么也没说,当然,我们国家是禁止非医学需要鉴定胎儿性别的,这里大家可以当做是一个小小的趣味,欢迎大家踊跃讨论!
如果大家感到有趣的话,可以关注“蛋宝宝”,后期会不定时为大家推送一些孕期及育儿知识,欢迎大家一起讨论,更好的状态迎接我们的宝宝,祝大家“好孕”。
亲爱的准妈妈,您好
上篇咱们说有了胎心胎芽,胎心胎芽出现的越早越好,一般六周到八周都会有胎心胎芽的,也有的发育晚,慢,九周才有,不过没关系,有了就是好消息……
有了胎心胎芽之后医生会告诉你12周左右去建档,做Nt。各个地方不一样,情况不一样,有的早有的晚,以我们河北石家庄来说,一般都是11——13周左右做。这也算是孕期里第一个大检查。包含血检,尿检,B超。建议早点去,因为要挂号,建档,医生会问你身高,体重,量血压,(体重,血压,之后每次去医院都会量的),末次例假,孕周,以便推算预产期。
第一项空腹采血,抽完血就是尿检,之后就可以吃东西啦。医院里人会很多,做B超很慢,排队时间长,那会儿就可以吃点面包啊啥的。而且不管是省立医院还是私立医院,做B超时墙上都会有个电视一样的东西,当你躺在检查床上,随着探头仪在肚子上滑来滑去,自己也会第一次见到肚子里的宝宝,那个让我们激动又高兴的小生命呀,是我们跟另一半专属的爱情结晶,是长的像我又像他的小人,更是我们一生都会用生命去爱的人,就在你肚子里,动来动去。那会儿虽然感觉不到胎动,但是咱们能看到生命的奇迹,并且会看得一清二楚,,像咱们第一次当妈的,还会控制不住地流下泪水呢,那是开心的眼泪呀。
省立医院各项检查都是自己一个人跑,采血厕所B超医生办公室,男士在外等着,他们只是陪伴,是拎包的挂件。所以一般准妈妈在跑上跑下排队做检查时,家属都是找个凳子玩手机,打游戏,等准妈妈出来。。
私立医院就不一样了,人少,除了厕所,去哪都有护士领着你们,而且不用排队,去哪都可以家属陪同,像B超,医生办公室,都是小意思啦。。缺少安全感的,又有经济能力的,可以选择私立。
Nt是11周到13周的时候做,属于B超检查的一项,是女性怀孕的常规检查,这个时间段是胎儿大脑发育的关键时期,这个时候做NT检查呢,准确率相对高一些,高达90%,B超可以用于检测胎儿颈后透明层的厚度,NT值若超过2.5毫米到三毫米,就可认为是异常的,特别是参考值超过三毫米,可能跟染色体异常有关。所以个人认为,这个是常规检查,也是必做检查。
这个是我的检查报告单,我做B超时,宝宝像视频里那样一直在跳。现在她已经一岁八个月了,真是个活泼好动的小姑娘。
这些检查都没问题就会建档,算是宝宝的第一份档案,也是宝宝一直在平安健康长大的证明,做了这个检查,恭喜您,已经平安的度过孕早期,之后就是最舒服的孕中期了,为期四个月。而且可以随时办理准生证了,这个石家庄每个地方都不一样,问自己产检的医生就好啦
今天的文章分享是 i 春秋作者flag0原创的文章,浅析导入表及导入表注入的相关内容,文章篇幅较长,阅读时长约15分钟,文章未经许可禁止转载!
导入表的概述
导入表是逆向和病毒分析中比较重要的一个表,在分析病毒时几乎第一时间都要看一下程序导入表的内容,判断程序大概用了哪些功能。
导入表位于数据目录项中的第二项,一般会有多个,每调用一个DLL便存在一张导入表,导入表记录了导入的dll中被调用的函数地址。
导入表结构体 IMAGE_IMPORT_DESCRIPTOR
typedef struct _IMAGE_IMPORT_DESCRIPTOR{ union{ DWORD Characteristics; DWORD OriginalFirstThunk; }; DWORD TimeDataStamp; DWORD ForwarderChain; DWORD Name; DWORD FirstThunk;} IMAGE_IMPORT_DESCRIPTOR;typedef IMAGE_IMPORT_DESCRIPTOR UNALGNED *PIMAGE_IMPORT_DESCRIPTOR;OriginalFirstThunk 指向导入名称表INT(Import Name Table)的RVA,INT是IMAGE_THUNK_DATA结构的数组,以内容为0的IMAGE_THUNK_DATA结构结束,每个IMAGE_THUNK_DATA指向IMAGE_IMPORT_BY_NAME结构。TimeDataStamp 时间戳,当其值为-1时,采用绑定导入技术进行加载。Name,指向存储函数名字的RVA。FirstThunk 指向导入地址表IAT(Import Address Table)的RVA,IAT与INT结构相同,也是一个IMAGE_THUNK_DATA结构的数组。
导入绑定技术
一般情况下,在程序加载前IAT表和INT表中的内容相同,都是程序引用的dll中的函数名或序号,加载完成后IAT表中将替换为函数的真正地址。
但在加载前IAT表中直接写绝对地址是可以实现的,并且具有启动速度快的优点,但是如果在dll重定位时,没能占据自身ImageBase处的地址,则需要修复绝对地址,当dll被修改时,IAT表中对应的函数地址可能被改,需要修复函数地址。
这种方式被称为绑定导入,在Windows自带的记事本中,就采用了这种方式。
IMAGE_THUNK_DATA
typedef struct _IMAGE_THUNK_DATA32 { union { PBYTE ForwarderString; PDWORD Function; DWORD Ordinal; PIMAGE_IMPORT_BY_NAME AddressOfData; } u1; } IMAGE_THUNK_DATA32; typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;Ordinal 被导入的API的序号值AddressOfData 指向IMAGE_IMPORT_BY_NAME的RVA
当IMAGE_THUNK_DATA值的最高位为1时,表示函数以序号方式导入,这时低31位被看做一个函数序号,当对号为0时,表示函数以字符串类型的函数名方式输入,这时双字的值是一个RVA,指向一个IMAGE_IMPORT_BY_NAME结构。
IMAGE_IMPORT_BY_NAME
存储了一个输入函数的相关信息
typedef struct _IMAGE_IMPORT_BY_NAME { WORD Hint; BYTE Name[1]; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;Hint 记录了函数在DLL的导出表中的序号,不是必须的,可以为空。Name 输入函数的函数名,是一个字符串以0结尾。
导入地址表IAT
IAT由PE装载器重写,PE装载器先搜索OriginalFirstThunk指向的INT表,如果找到,则遍历数组,找出每个IMAGE_IMPORT_BY_NAME结构所指向的输入函数的地址,加载器用函数真正的日寇地址代替由FirstThunk指向的IMAGE_THUNK_DATA数组里元素的值。
在加载前,非导入绑定情况下,INT表与IAT表中的内容是一样的。
PE文件加载后,IAT表被替换为函数的入口地址。
在加载前,可以看到:
FirstThunkFOA(23280)->IMAGE_THUNK_DATA32(0242BC)->IMAGE_IMPORT_BY_NAME(232B0)->Name="MessageBoxA"
在加载后的内存中,可以看到:
FirstThunkFOA(42428C)->IMAGE_THUNK_DATA32(77D5050B)函数地址
打印输出导入表
定位导入表
获得数据目录项第二项中的VirtualAddress 将其RVA转为FOA,用以定位到导入表结构,将导入表结构中的DWORD Name打印输出,即定位导入表,打印DLL名。
遍历INT表
通过导入表中的OriginalFirstThunk定义到INT表,以此判断IMAGE_THUNK_DATA数组的最高位是否为1,如果为1则按到导出序号导出,如果为0则其指向IMAGE_IMPORT_BY_NAME的RVA,将其转换成FOA,定位到IMAGE_IMPORT_BY_NAME,输出函数名字,依次遍历,直到数组结尾。
遍历IAT表
通过导入表中的FirstThunk定义到IAT表,余下方法同上。
实现代码
// PrintImport.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "stdlib.h"#include "windows.h"size_t FileLength(FILE *fp){ size_t num; fseek(fp,0,SEEK_END);//将文件指针移动到文件尾部 num = ftell(fp);//获取文件指针的当前位置 fseek(fp,0,SEEK_SET); return num;}LPVOID readFile(PCHAR path)//将文件中的数据读取到内存中{ FILE* fp; size_t len; LPVOID pFileBuffer; fp = fopen(path,"rb"); if(fp == NULL) { printf("error\n"); } len = FileLength(fp);//获取文件大小 pFileBuffer = (LPVOID)malloc(len);//申请动态内存 fread(pFileBuffer,len,1,fp); fclose(fp); return pFileBuffer;}DWORD RVATOFOA(DWORD RVA,LPVOID pFileBuffer){ DWORD FOA = NULL; PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeaders = NULL; PIMAGE_FILE_HEADER pFileHeader = NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader); if(RVA <= pOptionalHeader->SizeOfHeaders) return RVA; //此处不需要减去ImageBase 此处的RVA是基于FileAliment和SectionAliment来说的,并不是真正的内存中的RVA,此处的程序并没有在内存中运行 for(;RVA > (pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize);pSectionHeader++);//定位到所在节 FOA = RVA - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; return FOA;}DWORD FOATORVA(DWORD FOA,LPVOID pFileBuffer){ DWORD RVA = NULL; PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeaders = NULL; PIMAGE_FILE_HEADER pFileHeader = NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader); if(FOA <= pOptionalHeader->SizeOfHeaders) return FOA; //此处不需要减去ImageBase 此处的RVA是基于FileAliment和SectionAliment来说的,并不是真正的内存中的RVA,此处的程序并没有在内存中运行 for(;FOA > (pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize);pSectionHeader++);//定位到所在节 RVA = FOA - pSectionHeader->PointerToRawData + pSectionHeader->VirtualAddress ; return RVA;}VOID PrintImport(LPVOID pFileBuffer){ PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头 PIMAGE_NT_HEADERS pNtHeaders = NULL;//NT头 PIMAGE_FILE_HEADER pFileHeader = NULL;//标准PE头 PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;//拓展PE头 PIMAGE_SECTION_HEADER pSectionHeader = NULL;//节表 PIMAGE_SECTION_HEADER pNewSec = NULL;//新节表结构 PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL; //导出表结构体 PIMAGE_IMPORT_DESCRIPTOR pImportDescriptop = NULL;//导入表结构体 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER); //定位导入表地址 DWORD offsetImportFoa = RVATOFOA(pOptionalHeader->DataDirectory[1].VirtualAddress,pFileBuffer); //printf(); pImportDescriptop = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pFileBuffer + offsetImportFoa); while(pImportDescriptop->Name != NULL && pImportDescriptop->OriginalFirstThunk != NULL && pImportDescriptop->FirstThunk != NULL) { DWORD offsetDllNameFoa = RVATOFOA(pImportDescriptop->Name,pFileBuffer); PCHAR DllName = (PCHAR)((DWORD)pFileBuffer + offsetDllNameFoa); printf("\nDLLName:%s ",DllName); printf("OriginalFirstThunk:%x\n",pImportDescriptop->OriginalFirstThunk); DWORD offsetThunkFOA = RVATOFOA(pImportDescriptop->OriginalFirstThunk,pFileBuffer); PDWORD ImageThunk = (PDWORD)((DWORD)pFileBuffer + offsetThunkFOA); printf("======INT======\n"); while(*ImageThunk != 0x0000) { printf("ThunkValue:%x ",*ImageThunk); PIMAGE_IMPORT_BY_NAME IBName = NULL; try{ if(*ImageThunk & 0x80000000) { printf("按序号导出:%x\n",*ImageThunk & 0x7FFFFFFF); }else { DWORD IBNameFoa = RVATOFOA(*ImageThunk,pFileBuffer); IBName = (PIMAGE_IMPORT_BY_NAME)((DWORD)pFileBuffer+IBNameFoa); printf("Hit Name:%x-%s\n",IBName->Hint,IBName->Name); } ImageThunk++; }catch(...) { printf("\n"); ImageThunk++; } } printf("======IAT======\n"); DWORD FirstThunkFOA = RVATOFOA(pImportDescriptop->FirstThunk,pFileBuffer); ImageThunk = (PDWORD)((DWORD)pFileBuffer + FirstThunkFOA); while(*ImageThunk != 0x0000) { printf("ThunkValue:%x ",*ImageThunk); PIMAGE_IMPORT_BY_NAME IBName = NULL; try{ if(*ImageThunk & 0x80000000) { printf("按序号导出:%x\n",*ImageThunk & 0x7FFFFFFF); }else { DWORD IBNameFoa = RVATOFOA(*ImageThunk,pFileBuffer); IBName = (PIMAGE_IMPORT_BY_NAME)((DWORD)pFileBuffer+IBNameFoa); printf("Hit Name:%x-%s\n",IBName->Hint,IBName->Name); } ImageThunk++; }catch(...) { printf("\n"); ImageThunk++; } } pImportDescriptop++; }}int main(int argc, char* argv[]){ LPVOID pFileBuffer = NULL; LPVOID pNewSecFoa = NULL; PCHAR path = "C:\\飞鸽传书.exe."; pFileBuffer = readFile(path); PrintImport(pFileBuffer); system("pause"); return 0;}
导入表注入
工具及运行环境:
用于实验的程序:飞鸽传书dll文件Uedit编辑器LoadPE实验环境:Windows Xp实验程序下载:
链接:
https://pan.baidu/s/1pWWsqkLb_hjF7ksfnMkqeQ
提取码:x5b7
原理
当exe被加载时,系统会根据exe导入表信息来加载需要用到的DLL,导入表注入的原理就是修改exe导入表,将自己的DLL添加到exe的导入表中,这样exe运行时可以将自己的DLL加载到exe的进程空间。
实现步骤
1、新增节表用来存储移动后的导入表(这里也可以扩大节,或者是找节区的空白区);
2、根据目录项(第二个值就是导入表)得到导入表的VirtualAddress和Size;
3、将VirtualAddress RVA转FOA 定位到导入表;
4、将原导入表全部Copy到空白区(只需要移动原导入表,不需要改变OriginalFirstThunk和FirstThunk);
5、在新的导入表后面,追加一个导入表;
6、在原导入表IID所在的内存空间,追加8个字节的INT表,8个字节的IAT表,追加一个IMAGE_IMPORT_BY_NAME 结构,前2个字节是0 后面是函数名称字符串;
7、将IMAGE_IMPORT_BY_NAME结构的RVA赋值给INT和IAT表中的第一项,并修正导入表的OriginalFirstThunk和FirstThunk;
8、分配空间存储DLL名称字符串 并将该字符串的RVA赋值给Name属性;
9、修正IMAGE_DATA_DIRECTORY结构的VirtualAddress和Size。
手动实现
1、根据目录项,得到导入表的VritualAddress为01CE80,RVA->FOA = 1CE80
2、定位到导入表
导入表的大小为1cf48 - 1ce80 = 0xC8 = 200
3、寻找代码空白区
我们需要寻找一个空间大小>240字节的空白区[原先的导入表(200) + 新增导入表(20) + 结束符(20)]
节区的代码空白区大小 = SizeofRawData - VirtualSize
.text节满足我们的要求,我们定位到代码空白区
4、将原导入表复制到空白区
将原导入表复制到1a730处
从后面的空白处开始删除200个字节(因为复制粘贴并不是覆盖原来的,而是新增了200个字节,并将原来的字节向后填充)。
5、在新的导入表后,追加一个导入表。
即从1a7f8开始,将20个字节修改为FFFFFFFF 00000000 00000000 FFFFFFFF FFFFFFFF,已备后续修改。
对应如下:
6、追加一个IMAGE_IMPORT_BY_NAME结构,前2个字节是0后面是函数名称字符串。
原导入表的位置为1ce80,在原导入表所在的内存空间,追加8个字节的INT表,8个字节的IAT表。
7、将IMAGE_IMPORT_BY_NAME结构的RVA赋值给INT和IAT表中的第一项。
IMAGE_IMPORT_BY_NAME的FOA地址为1ce90,转换成RVA为1ce90。
转换为小端显示:90 ce 01 00,将其填充到INT表和IAT表中。
修正导入表的OriginalFirstThunk
INT的FOA地址为:01ce80 RVA为01ce80,转换成小端显示为,80 CE 01 00修正OriginalFirstThunk。
IAT的FOA地址为:01ce88 RVA为01ce88,转换成小端显示为,88 CE 01 00修正FirstThunk。
8、分配空间存储DLL名称字符串,并将该字符串的RVA赋值给Name属性。
在新增的IMAGE_IMPORT_BY_NAME后(地址为1cea1),追加DLL名称字符串。
1cea1 FOA转换为RVA 1cea1,转换成小端显示A1 CE 01 00,修正导入表Name。
9、修正IMAGE_DATA_DIRECTORY结构的VirtualAddress和Size。
Size=DC+0x14(新增了一个导入表)
VirtualAddress = FOA:1A730转换为RVA为1A730转换成小端显示:30 A7 01 00
修正VirtualAddress 和Size:
将InjectDll.dll放到与被修改的程序同一目录下,运行程序。
成功弹出弹窗!
代码实现:// ImportInject.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "stdlib.h"#include "windows.h"size_t FileLength(FILE *fp){ size_t num; fseek(fp,0,SEEK_END);//将文件指针移动到文件尾部 num = ftell(fp);//获取文件指针的当前位置 fseek(fp,0,SEEK_SET); return num;}LPVOID readFile(PCHAR path)//将文件中的数据读取到内存中{ FILE* fp; size_t len; LPVOID pFileBuffer; fp = fopen(path,"rb"); if(fp == NULL) { printf("error\n"); } len = FileLength(fp);//获取文件大小 pFileBuffer = (LPVOID)malloc(len);//申请动态内存 fread(pFileBuffer,len,1,fp); fclose(fp); return pFileBuffer;}DWORD RVATOFOA(DWORD RVA,LPVOID pFileBuffer){ DWORD FOA = NULL; PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeaders = NULL; PIMAGE_FILE_HEADER pFileHeader = NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader); if(RVA <= pOptionalHeader->SizeOfHeaders) return RVA; //此处不需要减去ImageBase 此处的RVA是基于FileAliment和SectionAliment来说的,并不是真正的内存中的RVA,此处的程序并没有在内存中运行 for(;RVA > (pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize);pSectionHeader++);//定位到所在节 FOA = RVA - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData; return FOA;}DWORD FOATORVA(DWORD FOA,LPVOID pFileBuffer){ DWORD RVA = NULL; PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNtHeaders = NULL; PIMAGE_FILE_HEADER pFileHeader = NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader); if(FOA <= pOptionalHeader->SizeOfHeaders) return FOA; //此处不需要减去ImageBase 此处的RVA是基于FileAliment和SectionAliment来说的,并不是真正的内存中的RVA,此处的程序并没有在内存中运行 for(;FOA > (pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize);pSectionHeader++);//定位到所在节 RVA = FOA - pSectionHeader->PointerToRawData + pSectionHeader->VirtualAddress ; return RVA;}BOOL ImportInject(LPVOID pFileBuffer,PCHAR pInjectDllName,PCHAR pImportFunName)//Inject{ PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头 PIMAGE_NT_HEADERS pNtHeaders = NULL;//NT头 PIMAGE_FILE_HEADER pFileHeader = NULL;//标准PE头 PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;//拓展PE头 PIMAGE_SECTION_HEADER pSectionHeader = NULL;//节表 PIMAGE_SECTION_HEADER pNewSec = NULL;//新节表结构 pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader + pFileHeader->SizeOfOptionalHeader); //判断是否有足够的空间添加节表 if ((pOptionalHeader->SizeOfHeaders - ((DWORD)pSectionHeader - (DWORD)pFileBuffer + pFileHeader->NumberOfSections * 40)) < 80) { printf("空间不足"); return false; } //新增节表结构 pNewSec = (PIMAGE_SECTION_HEADER)(pSectionHeader + pFileHeader->NumberOfSections); //修改节表内容 memcpy(pNewSec->Name,".export",8);//修改节表名 PIMAGE_SECTION_HEADER upSecHeader = (PIMAGE_SECTION_HEADER)(pSectionHeader + pFileHeader->NumberOfSections-1); if(upSecHeader->Misc.VirtualSize > upSecHeader->SizeOfRawData)//修改节表VrituallAddress { pNewSec->VirtualAddress = upSecHeader->VirtualAddress + upSecHeader->Misc.VirtualSize; }else{ pNewSec->VirtualAddress = upSecHeader->VirtualAddress + upSecHeader->SizeOfRawData; } pNewSec->SizeOfRawData = 0x1000;//新增的节区的大小 pNewSec->PointerToRawData = upSecHeader->PointerToRawData + upSecHeader->SizeOfRawData;//文件中的偏移 pNewSec->Characteristics = 0x60000020;//修改属性(可执行) //在新增节表后增加40个字节的空白区 memset((LPVOID)(pNewSec+1), 0, sizeof(*pNewSec)); //修改NT头属性 pFileHeader->NumberOfSections += 1;//修改NumberOfSection数量 pOptionalHeader->SizeOfImage += 0x1000;//修改SizeOfImage大小 LPVOID NewBuffer = malloc(pOptionalHeader->SizeOfImage);//申请内存 memset(NewBuffer, 0, pOptionalHeader->SizeOfImage);//初始化内存 memcpy(NewBuffer, pFileBuffer,pOptionalHeader->SizeOfImage);//复制内存 //定位导入表 DWORD ImportDescrFOA = RVATOFOA(pOptionalHeader->DataDirectory[1].VirtualAddress,pFileBuffer); PIMAGE_IMPORT_DESCRIPTOR ImportDescr = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)NewBuffer + ImportDescrFOA); LPVOID pNewSecAddr = (LPVOID)((DWORD)NewBuffer+pNewSec->PointerToRawData); memcpy(pNewSecAddr,ImportDescr,pOptionalHeader->DataDirectory[1].Size);//复制导入表 //添加新的导入表 PIMAGE_IMPORT_DESCRIPTOR NewImport = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)NewBuffer + pNewSec->PointerToRawData + pOptionalHeader->DataDirectory[1].Size - sizeof(*NewImport));//新的导入表 //添加INT、IAT、Name PIMAGE_THUNK_DATA NewINT = (PIMAGE_THUNK_DATA)((DWORD)NewBuffer + ImportDescrFOA); PIMAGE_THUNK_DATA NewIAT = (PIMAGE_THUNK_DATA)((DWORD)NewBuffer + ImportDescrFOA + 0x8); PCHAR NewDllName = (PCHAR)((DWORD)NewBuffer + ImportDescrFOA + 0x8 + 0x8); memcpy(NewDllName,pInjectDllName,strlen(pInjectDllName)+0x1);//Dll名 PIMAGE_IMPORT_BY_NAME NewName = (PIMAGE_IMPORT_BY_NAME)((DWORD)NewBuffer + ImportDescrFOA + 0x8 + 0x8 + strlen(pInjectDllName)+0x1); NewName->Hint = 0x0; memcpy(NewName->Name,pImportFunName,strlen(pImportFunName)+1);//导出函数名 memset(NewINT, 0, 0xf);//清空原有数据 NewINT->u1.AddressOfData = (PIMAGE_IMPORT_BY_NAME)FOATORVA((DWORD)(ImportDescrFOA + 0x8 + 0x8 + strlen(pInjectDllName)+0x1),NewBuffer); NewIAT->u1.AddressOfData = (PIMAGE_IMPORT_BY_NAME)FOATORVA((DWORD)(ImportDescrFOA + 0x8 + 0x8 + strlen(pInjectDllName)+0x1),NewBuffer); //修正新增加的导入表 NewImport->OriginalFirstThunk = FOATORVA(ImportDescrFOA,NewBuffer); NewImport->FirstThunk = FOATORVA(ImportDescrFOA + 0x8,NewBuffer); NewImport->Name = FOATORVA(ImportDescrFOA + 0x8 + 0x8,NewBuffer); memset((LPVOID)((DWORD)NewImport+sizeof(*NewImport)),0,sizeof(*NewImport)); //修正 数据段 pDosHeader = (PIMAGE_DOS_HEADER)NewBuffer; pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew); pFileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeaders + 4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + IMAGE_SIZEOF_FILE_HEADER); pOptionalHeader->DataDirectory[1].VirtualAddress = pNewSec->VirtualAddress; pOptionalHeader->DataDirectory[1].Size += 0x20; FILE* fp = fopen("C:\\fg.exe","wb+"); fwrite(NewBuffer,pOptionalHeader->SizeOfImage,1,fp); fclose(fp); return 0;}int main(int argc, char* argv[]){ LPVOID pFileBuffer = NULL; LPVOID pNewSecFoa = NULL; PCHAR path = "C:\\飞鸽传书.exe"; pFileBuffer = readFile(path); ImportInject(pFileBuffer,"InjectDll.dll","ExportFunction"); system("pause"); return 0;}
以上是今天分享的内容,大家看懂了吗?
清宫表
这个基本不用讨论,完全没有科学依据。但多数婆婆妈妈对此迷之自信 那么就拿出来说说吧。说到这个清宫表,似乎能感觉到天地浑沌,大自然孕育万物般的神乎,但它的理论根本就站不住脚,虚岁周岁,月经月份,不想说了,一派胡言。如果是靠谱的,那么想要男女就是人为可以干预的了,又怎么可能呢。我收集过周围不下于100个样本,结果是男女几乎各对半,几率问题。如果你觉得准,可能是巧合,因为不是男就是女,只有两种性别,信清宫表不如猜硬币。
HCG:
刚知道hcg的时候觉得是有点依据的,毕竟根据绒毛来看有理可依,可这个要想准确,要知道确切的排卵日,hcg峰值时间,一般人早期不会频繁去验血专门来查hcg峰值,每个人出现峰值的时间也不一样。而且胚胎早期的绒毛分泌差异没那么明显。拿我自己来说,7周时验血hcg都八万多了,这个值是不低的,照理说女孩可能性大,最后生的是男孩。所以总结是此法相对来说有点依据,可作参考,但用起来未必顺手,并且只是几率大,而不是板上钉钉。
孕囊:
这个在我总结的所有看男女中应该算是第二不靠谱的了,孕囊就好比人的高矮胖瘦,每个人都不同,用这种方法来看男女显然不可取,有医生朋友说圆形孕囊意味着胚胎发育的比较好,跟男女没关系,这个就见仁见智吧。不管三个数据也好,两个数据也好,都是看不出男女的。就不拿朋友举例子了,现身说法,我7周左右孕囊是37*35*27,可不圆滚滚的,照理说应该是女孩的,实际也不是。一句话总结,仅供娱乐吧。
nub原理:
源于国外医生,不知道的可以度娘,这里不普及知识,只说准确不准确,我网上找着看了些文章和一些妈妈的NT图,得出结论,只要是12周左右比较清楚没有遮住关键部位的B超图,那么看男女的准确率还是非常高的,我自己11+6的B超图,一看就是男孩,也帮周围的一些朋友看过,有的图片时间不对,有的太小,有的模糊看不清,但凡清楚地能看到的都是准确的。
唐筛:
原理可以和hcg原理比较,但很多人孕周未必测算的精准,也有的在孕早期吃过或注射过黄体酮,会使数值有所变化。而且我亲身体验也是不准确的,小小宇的唐筛数据是hcg>1,AFP<1,照理是典型女孩数据;我姐当时唐筛高危,做了无创,hcg>2,AFP<0.5,也是男孩。我收集过一个帖子里的数据,几年前一个很火的育儿网站一个楼主发帖子要给别人看唐晒单猜男女,很多人回帖子晒出糖筛单子问她,我挨个点进去看她们的主页(很多人后来会发报喜贴可以看出生男生女),得出的结果是唐筛不准,很不准,比hcg还不靠谱。
胎动:
胎动这个我也觉得是没有依据的,就像每个宝宝的性格一样 有的安静一些,有的活泼一些,胎位也不一样,所以胎动的地方不一样也是可以理解的。我怀儿子时左右都动,有时踢踢打打,有时鼓大包有时鼓小包,有时爱动有时不太动,并没有什么规律。总结一句,根据胎动看性别和孕囊一样不靠谱。
胎心:
根据收集觉得准确率比较高的判断依据,但操作起来比较麻烦。因为胎心要到后期宝宝完全发育好了之后才会比较稳定,前期胎心都比较快。大概30周以后会逐渐稳定。男孩胎心一般偏慢,女孩偏快,以140为分水岭。但不是根据一次两次B超就可以得出结论。有的宝宝B超时动的比较厉害,那很可能即使是男孩心跳也会快,就跟大人运动时心跳快是一个道理,有的宝宝B超时刚好睡着了或比较安静,那么可能即使女孩心跳也慢。所以如果后期好几次(起码>3)B超心跳都比较快或比较慢,那么判断应该几率比较大了。按照同样的方法,我点击了晒胎心的妈妈的主页,一般胎心很多次都比较快的确实女孩概率大些。
双顶径:、
传统的说法是男孩头大腿短,女孩头小腿长。即男孩双顶径-股骨长>2,女孩双顶径-股骨长<2。这就像说男性身高普遍要高于女性一样,大概率是这样。可也有例外啊,特别是现在大家生活条件好了,营养好了 身高差距也在缩小。现在的孕妇营养都挺好的 小孩发育也都差不了多少,况且也跟遗传有关。所以此条也只能说有点依据,但不能说就是正确的。我宝宝从28周起确实双顶径减股骨长都大于2,但身边也有不少男孩双顶径减股骨小于2的。
肚形:
肚形看男女这个比较古老了,很多人对此深信不疑。确实有的人肚子特征一看就是男孩或女孩。比如身上哪里都不胖只有肚并且尖的是典型的男孩肚,如果胖的地方比较多,肚子不规则,一般女孩概率大。
像董璇微博晒出来和关悦一起拍的孕妇照,真的非常典型,董璇一看就是女孩,关悦则是男孩无疑。
但很多人肚子并不典型,看不出来。并且肚形和个人的孕前体型也有关系。孕前就很胖的怀孕后体重增加看起来会更胖,怀孕前就苗条加上孕后控制的比较好的,无论怀男怀女看起来体态都会好很多,除了肚子其他地方并不会显胖。所以总的来说肚形只针对比较典型的才准。有很多型的是不准的。
其他的还有看脚肿不肿啦,尿检ph啦,中性粒细胞啦,妊娠线啦等等,都是不太准的。
以上方法,仅供娱乐。