首页
动态
文章归档
友情链接
留言簿
关于
推荐
免费图床
统计
朋友圈集赞
二维码生成
高中笔记
Search
1
全网首发-小米AX6000路由器解锁ssh并固化ssh+2.5G有线mesh组网+公网访问路由后台+红米AX6/小米AX6/AX3600/AX6000/AX9000全系列适用
6,907 阅读
2
青龙面板必装依赖及青龙各种问题解决
3,946 阅读
3
NAS一键批量清除重复文件
3,596 阅读
4
群辉DSM7.0.1安装bootstrap后解决wget: error while loading shared libraries: libgnuintl.so.8: cannot open shared object file: No such file or directory
1,607 阅读
5
《爱情公寓4》全集高清迅雷下载
908 阅读
闲言碎语
学习
福利
技术百科
WordPress
Typecho
软件资源
iPhone
Android
PC软件
CODE
C
VB
PHP
NAS
青龙
登录
Search
标签搜索
wordpress
News
iphone
Typecho
vb
iOS
technology
渗透
QQ
php
NAS
hack
talk
福利
JavaScript
c++
diy
c
英语
免杀
Jonty
累计撰写
297
篇文章
累计收到
1,007
条评论
今日撰写
0
篇文章
首页
栏目
闲言碎语
学习
福利
技术百科
WordPress
Typecho
软件资源
iPhone
Android
PC软件
CODE
C
VB
PHP
NAS
青龙
页面
动态
文章归档
友情链接
留言簿
关于
推荐
免费图床
统计
朋友圈集赞
二维码生成
高中笔记
用户登录
登录
搜索到
285
篇与
Jonty
的结果
2013-07-07
DLL注入技术之REG注入
DLL注入技术之REG注入DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EXE文件中的API),或以被注入EXE的身份去执行一些操作等等。REG注入原理是利用在Windows 系统中,当REG以下键值中存在有DLL文件路径时,会跟随EXE文件的启动加载这个DLL文件路径中的DLL文件。当如果遇到有多个DLL文件时,需要用逗号或者空格隔开多个DLL文件的路径。HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ Windows\AppInit_DLLREG注入就好比在食堂(Windows 系统)发放给学生(EXE文件)饭菜(DLL文件)的过程中,食堂在将原有饭菜的基础上多发给一份紫菜鸡蛋汤(AppInit_DLL中的DLL文件),这个紫菜鸡蛋汤可以是英伟达的UI加速的DLL文件,也可以是是病毒文件的DLL,这就要看使用者是怎么利用这个特性了。设置完毕后,当我们启动一个EXE文件时(例如计算器),用调试器工具OllyDBG附加到计算器,调用OllyDBG菜单命令,“查看—可执行模块”,此时我们已经可以看到DLL文件已经附加在EXE文件中了我们可以利用这个特性来进行DLL的注入,接下来需要解决的就是关于注册表操作的Windows API了,如下所示:RegOpenKeyEx 打开注册表键值 RegQueryValueEx 查询键值 RegSetValueEx 设置键值 RegCloseKey 关闭键值主要代码如下://打开键值 nReg = RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_szRegPath, 0, KEY_ALL_ACCESS, &hKey); if(nReg != ERROR_SUCCESS) { return FALSE; } //查询键值 DWORD dwReadType; DWORD dwReadCount; TCHAR szReadBuff[1000] = {0}; nReg = RegQueryValueEx(hKey, _T("AppInit_DLLs"), NULL, &dwReadType, (BYTE*)&szReadBuff, &dwReadCount); if(nReg != ERROR_SUCCESS) { return FALSE; } //是否dll名称已经在内容中 tstring strCmpBuff; strCmpBuff = szReadBuff; if (!strCmpBuff.find(InjectFilePath)) { return FALSE; } //有字符串就加入空格 if (0 != _tcscmp(szReadBuff,_T(""))) { _tcscat_s(szReadBuff,_T(" ")); } _tcscat_s(szReadBuff,InjectFilePath); //把dll路径设置到注册表中 nReg = RegSetValueEx(hKey, _T("AppInit_DLLs"), 0, REG_SZ, (CONST BYTE*)szReadBuff, (_tcslen(szReadBuff)+1)*sizeof(TCHAR));当我们完成了注册表的注入时,并不是希望所有程序都运行DLL里面的内容,这时我们就需要在DLL中过滤窗口名称,让指定窗口名称的EXE文件运行DLL里的线程。所需API如下表所示:CreateThread 创建线程 Sleep 睡眠 EnumWindows 遍历窗口 GetWindowText 得到窗口名称 GetCurrentProcessId 得到当前进程ID GetWindowThreadProcessId 由HWND获得进程ID为了实现此功能,我们需要在注入的DLL中创建线程,并在线程中执行遍历窗口函数,我们需要先获取窗口名称,与我们想运行的EXE名称进行对比,并进行进程ID对比,因为不光只有一个EXE文件的运行实例,经过这些过滤后,我们就可以在指定的EXE文件中运行代码了。主要代码如下:BOOL CALLBACK lpEnumFunc(HWND hwnd, LPARAM lParam) { TCHAR str[MAXBYTE] = {0}; //得到窗口名称 GetWindowText(hwnd,str,sizeof(str)); //是否名称是计算器 if(0 == _tcscmp(str,_T("计算器"))) { //由于存在可能多个计算器,需要过滤线程ID //得到本身线程的ID DWORD dwCurrentProcessId = GetCurrentProcessId(); DWORD dwFindCurrentProcessId = 0; //得到窗口线程ID GetWindowThreadProcessId(hwnd,&dwFindCurrentProcessId); //比较 if (dwCurrentProcessId == dwFindCurrentProcessId) { *(PDWORD)lParam = 1; return FALSE; } } return TRUE; } DWORD ThreadProc(CMfcRegInjectDllApp* pThis) { //切换mfc模块 AFX_MANAGE_STATE(AfxGetStaticModuleState()); //等待1秒时间以便于让windows创建窗口 Sleep(1000); DWORD dwFind = 0; //遍历窗口,过滤窗口名称 EnumWindows(lpEnumFunc,(LPARAM)&dwFind); if (!dwFind) return 0; //显示对话框 if (!pThis->m_pUIDlg) { pThis->m_pUIDlg = new RegInjectMessageBox(); pThis->m_pUIDlg->Create(IDD_DIALOG1); pThis->m_pUIDlg->ShowWindow(SW_SHOW); pThis->m_pUIDlg->RunModalLoop(); } return 0; } BOOL CMfcRegInjectDllApp::InitInstance() { //CWinApp::InitInstance(); DWORD dwThreadId; m_hThread = ::CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ThreadProc, this, NULL,&dwThreadId); return TRUE; }REG注入操作简单易懂,甚至不用写程序都可以完成注入操作,但是正是由于他的简单性,每个EXE都被注入,效率低,程序的扩展性差。作者: xusir98来源: 黑客反病毒 (http://bbs.hackav.com)
2013年07月07日
80 阅读
0 评论
0 点赞
2013-07-07
DLL注入技术之ComRes注入
ComRes注入的原理是利用Windows 系统中C:\WINDOWS\system32目录下的ComRes.dll这个文件,当待注入EXE如果使用CoCreateInstance()这个API时,COM服务器会加载ComRes.dll到EXE中,我们利用这个加载过程,移花接木的把ComRes.dll替换掉,并在伪造的ComRes.dll,然后利用LoadLibrary()将事先准备好的DLL加载到目标的EXE中。1.编写测试文件为了向大家完整的演示ComRes注入的过程,我们需要先建立一个使用CoCreateInstance()函数的示例程序。新建atl的DLL工程,这个工程中只提供了一个简单的com接口方法TestMsgBox,主要代码如下:STDMETHODIMP CCMyCom::TestMsgBox(void) { // TODO: 在此添加实现代码 MessageBox(0,0,0,0); return S_OK; } 这时编译后会产生一个tlb文件,他是调用com接口方法工程中所要使用的导入文件。新建mfc对话框工程,在stdafx.h文件中加入#import "tlb文件路径\xxxx.tlb " no_namespace。添加一个BUTTON控件,双击后在单击事件中写入调用atl中com接口方法。主要代码如下:void CReplaceRescomInjectDlg::OnBnClickedCallcom() { // TODO: 在此添加控件通知处理程序代码 CoInitialize(NULL); CLSID clsid; HRESULT hr = CLSIDFromProgID(OLESTR("CallComDll.CMyCom"),&clsid); ICMyCom *ptr; hr = CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER, __uuidof(ICMyCom),(LPVOID*)&ptr); ptr->TestMsgBox(); CoUninitialize(); } 编译过后用XueTr观察下EXE中的DLL文件我们发现他并没有调用comres.dll这个文件我们已经发现comres.dll已经被com服务器装载到这个EXE文件中了。2.伪造comres.dll文件使用DEPENDS.EXE文件查看一下,发现只有一个导出函数COMResModuleInstance()。新建一个DLL工程,加入def文件,添加导出函数EXPORTS COMResModuleInstance在主工程cpp文件中,加入如下代码。HANDLE ghInst = 0; BOOL isLoad = FALSE; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: ghInst = hModule; if (!isLoad) { LoadLibrary(_T("D:\\MyDll\\ReplaceRescomInject\\Debug\\LoadLibraryDll.dll")); isLoad = TRUE; } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return TRUE; } int COMResModuleInstance() { return (int)ghInst; } 编译后得到的文件改名为comres.dll,然后将其剪切到其他文件夹下备用,这时读者会问,为什么是剪切尓不是拷贝呢?原因在于当在exe同级目录下有和C:\WINDOWS\system32一样的文件,exe会首先加载同级目录下的文件,而不会加载C:\WINDOWS\system32中的文件。3.替换comres.dll文件由于直接拷贝comres.dll文件到C:\WINDOWS\system32目录下会引起winows的文件系统保护机制,所以首先需要将C:\WINDOWS\system32\dllcache下的文件替换掉,然后再将其C:\WINDOWS\system32文件替换为我们伪造的文件。ComRes注入只需伪造与替换就可以完成,编程要求不高,方便使用,但是由于加载了ComRes.dll后,再想替换ComRes.dll文件就不可能了,因此想反复测试ComRes.dll文件就比较麻烦。
2013年07月07日
117 阅读
0 评论
0 点赞
2013-07-07
DLL注入技术之输入法注入
输入法注入原理是利用Windows系统中在切换输入法需要输入字符时,系统就会把这个输入法需要的ime文件装载到当前进程中,而由于这个Ime文件本质上只是个存放在C:\WINDOWS\system32目录下的特殊的DLL文件,因此我们可以利用这个特性,在Ime文件中使用LoadLibrary()函数待注入的DLL文件。1.编写Ime文件输入法的Ime文件其实就是个显式导出19个特殊函数的DLL文件。如果想编写输入法程序,那么这19个导出函数都需要仔细的研究,但是对于只想实现注入的我们,现在只需要对ImeInquire()有比较深的认识就可以了。ImeInquire()是启动并初始化当前Ime输入法函数,他的声明如下:BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo,LPTSTR lpszUIClass,LPCTSTR lpszOption)第一个参数lpIMEInfo比较重要,用于输入对Ime输入法初始化的内容结构,如果这个结构填写错误,就会导致输入法不能正常运行。第二个参数是输入一个class类名,我们需要先使用RegisterClassEx()注册出一个窗口类。初始化ImeInquire()主要代码如下所示://启动并初始化当前ime输入法 BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo,LPTSTR lpszUIClass,LPCTSTR lpszOption) { //输入法初始化过程 //系统根据它为INPUTCONTEXT.hPrivate分配空间 lpIMEInfo->dwPrivateDataSize = 0; lpIMEInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST | IME_PROP_IGNORE_UPKEYS | IME_PROP_END_UNLOAD; lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; lpIMEInfo->fdwSentenceCaps = IME_SMODE_NONE; lpIMEInfo->fdwUICaps = UI_CAP_2700; lpIMEInfo->fdwSCSCaps = 0; lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; // 注意该输入法基本窗口类必须注册,否则输入法不能正常运行 _tcscpy(lpszUIClass,CLSNAME_UI); return TRUE; } 注册出一个窗口类的主要代码如下:BOOL ImeClass_Register(HINSTANCE hInstance) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_IME; wc.lpfnWndProc = UIWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 2 * sizeof(LONG); wc.hInstance = hInstance; wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hIcon = NULL; wc.lpszMenuName = (LPTSTR)NULL; wc.lpszClassName = CLSNAME_UI; wc.hbrBackground = NULL; wc.hIconSm = NULL; if( !RegisterClassEx( (LPWNDCLASSEX)&wc ) ) return FALSE; return TRUE; } CLSNAME_UI是一个宏定义,如下:#define CLSNAME_UI _T("DLLCLASSNAME")在DllMain进程加载的过程中注册窗口类,主要代码如下:case DLL_PROCESS_ATTACH: if(!ImeClass_Register(hinstDLL)) return FALSE; //这里填写要load的DLL的路径 g_hModule = LoadLibrary(_T("D:\\MyDll\\ImeInject\\Debug\\MfcImeInjectDll.dll")); if (!g_hModule) { MessageBox(NULL,_T("模块没有load成功"),_T("提示"),MB_OK); } break; 此刻默认输出的DLL文件扩展名是.dll,与扩展名是.ime不符,则需要更改扩展名。2.编写装载输入法程序装载输入法的基本逻辑就是将他们编写的输入法设置为默认输入法,这样只要系统中所有进程都会默认加载他们的恶意输入法程序。黑客们首先需要得到系统当前的默认的输入法,以便恢复时使用。然后需要将ime文件拷贝到C:\WINDOWS\system32目录下,最后将装载成功后将我们的输入法设置成为默认输入法,主要代码如下:void CMfcImeInjectDlg::OnBnClickedAttach() { // TODO: 在此添加控件通知处理程序代码 //得到默认的输入法句柄并保存 ::SystemParametersInfo( SPI_GETDEFAULTINPUTLANG, 0, &m_retV, 0); //拷贝到system目录,只有ime文件在system32下才能装载成功 CopyFile( _T("D:\\MyDll\\ImeInject\\Debug\\MyImeDll.ime"), _T("C:\\WINDOWS\\system32\\MyImeDll.ime"), FALSE); //装载输入法 m_hImeFile = ImmInstallIME( _T("MyImeDll.ime"), _T("我的输入法")); if( ImmIsIME(m_hImeFile) ) { //设置为默认输入法 SystemParametersInfo( SPI_SETDEFAULTINPUTLANG, 0, &m_hImeFile, SPIF_SENDWININICHANGE); MessageBox(_T("安装输入法成功")); } } 3.编写卸载输入法:当新建进程不再需要注入时,我们就需要卸载输入法。卸载输入法时需要先判定系统当前的输入法不是其原有默认输入法,确认无误后将系统的默认输入法恢复后,再将恶意输入法卸载即可,主要代码如下:void CMfcImeInjectDlg::OnBnClickedDettach() { // TODO: 在此添加控件通知处理程序代码 ::SystemParametersInfo( SPI_SETDEFAULTINPUTLANG, 0, &m_retV, SPIF_SENDWININICHANGE); if (UnloadKeyboardLayout(m_hImeFile)) { MessageBox(_T("输入法卸载成功")); } } 输入法注入的实现需要对输入法IME文件的生成有所了解,API使用较多,所以实现起来比较难,但是由于系统存在多个输入法,被注入进程很难判别当前是可信赖输入法还是用于注入的恶意输入法,所以难以阻止,大大提高了注入的几率作者: xusir98来源: 黑客反病毒 (http://bbs.hackav.com)
2013年07月07日
68 阅读
0 评论
0 点赞
2013-07-07
DLL注入技术之远线程注入
DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EXE文件中的API),或以被注入EXE的身份去执行一些操作等等。 远线程注入原理是利用Windows 系统中CreateRemoteThread()这个API,其中第4个参数是准备运行的线程,我们可以将LoadLibrary()填入其中,这样就可以执行远程进程中的LoadLibrary()函数,进而将我们自己准备的DLL加载到远程进程空间中执行。 当然除了CreateRemoteThread()和LoadLibrary()这个两个主要的API还是远远不够的,我们还需要以下表格所示的API:OpenProcess 打开远程进程 VirtualAllocEx 在远程进程中申请空间 WriteProcessMemory 在远程进程中写入数据 WaitForSingleObject 等待信号量 VirtualFreeEx 释放远程进程中申请空间 CloseHandle 关闭句柄主要代码如下:int CRemoteThreadInjectDLL::InjectDll(DWORD dwProcessId, PTCHAR szDllName) { if (szDllName[0] == NULL) return -1; //提高权限相关操作 EnablePrivilege(TRUE); //1. 打开进程 HANDLE hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, //打开进程权限 FALSE, //是否可继承 dwProcessId); //进程ID if (hProcess == INVALID_HANDLE_VALUE) return -1; //2. 在远程进程中申请空间 LPVOID pszDllName = ::VirtualAllocEx(hProcess, //远程进程句柄 NULL, //建议开始地址 4096, //分配空间大小 MEM_COMMIT, //空间初始化全0 PAGE_EXECUTE_READWRITE); //空间权限 if (NULL == pszDllName) { return -1; } //3. 向远程进程中写入数据 BOOL bRet = ::WriteProcessMemory( hProcess, pszDllName, szDllName, MAX_PATH, NULL); if (NULL == bRet) { return -1; } //4. 在远程进程中创建远程线程 m_hInjecthread = ::CreateRemoteThread(hProcess, //远程进程句柄 NULL, //安全属性 0, //栈大小 (LPTHREAD_START_ROUTINE)LoadLibrary, //进程处理函数 pszDllName, //传入参数 NULL, //默认创建后的状态 NULL); //线程ID if (NULL == m_hInjecthread) { DWORD dwErr = GetLastError(); return -1; } //5. 等待线程结束返回 DWORD dw = WaitForSingleObject(m_hInjecthread, -1); //6. 获取线程退出码,即LoadLibrary的返回值,即dll的首地址 DWORD dwExitCode; GetExitCodeThread(m_hInjecthread, &dwExitCode); m_hMod = (HMODULE)dwExitCode; //7. 释放空间 BOOL bReturn = VirtualFreeEx(hProcess, pszDllName, 4096, MEM_DECOMMIT); if (NULL == bReturn) { return -1; } CloseHandle(hProcess); hProcess = NULL; //恢复权限相关操作 EnablePrivilege(FALSE); return 0; } 此外,我们还需要提升进程权限以便于提高注入成功率,所需API如下表所示:OpenProcessToken 得到令牌句柄 LookupPrivilegeValue 得到权限值 AdjustTokenPrivileges 提升令牌句柄权限主要代码如下:int CRemoteThreadInjectDLL::EnablePrivilege(bool isStart) { //1. 得到令牌句柄 HANDLE hToken = NULL; //令牌句柄 if (!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ, &hToken)) { return FALSE; } //2. 得到特权值 LUID luid = {0}; //特权值 if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { return FALSE; } //3. 提升令牌句柄权限 TOKEN_PRIVILEGES tp = {0}; //令牌新权限 tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = isStart ? SE_PRIVILEGE_ENABLED : 0; if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL)) { return FALSE; } //4. 关闭令牌句柄 CloseHandle(hToken); return 0; } 当要在指定的进程中加载DLL时,我们就需要过滤指定名称的进程,这时遍历进程ID并进行对比,得到所指定的进程,所需API如表所示:CreateToolhelp32Snapshot 创建进程快照 Process32First 第一个进程快照 Process32Next 循环下一个进程快照主要代码如下:DWORD CRemoteThreadInjectDLL::GetProcessId(PTCHAR pszProcessName) { HANDLE hProcess = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (INVALID_HANDLE_VALUE == hProcess) { return 0; } DWORD dwProcessId = 0; PROCESSENTRY32 process32 = {0}; process32.dwSize = sizeof(PROCESSENTRY32); BOOL bRetProcess = FALSE; bRetProcess = ::Process32First(hProcess, &process32); do { if (_tcscmp(pszProcessName, process32.szExeFile) == 0) { dwProcessId = process32.th32ProcessID; break; } bRetProcess = ::Process32Next(hProcess, &process32); }while (bRetProcess); ::CloseHandle(hProcess); return dwProcessId; }
2013年07月07日
92 阅读
0 评论
0 点赞
2013-07-02
DLL注入技术之劫持进程创建注入
DLL注入技术之劫持进程创建注入劫持进程创建注入原理是利用Windows系统中CreateProcess()这个API创建一个进程,并将第6个参数设为CREATE_SUSPENDED,进而创建一个挂起状态的进程,利用这个进程状态进行远程线程注入DLL,然后用ResumeThread()函数恢复进程。1.创建挂起的进程下面是创建一个挂起的计算器程序进程的主要代码:代码: STARTUPINFO si = {0}; si.cb = sizeof si; si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; PROCESS_INFORMATION pi; TCHAR cmdline[MAXBYTE] =_T("calc.exe"); BOOL bRet = ::CreateProcess( NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, //需要注意的参数 NULL, NULL, &si, &pi);2.向挂起的进程中进行远程线程注入DLL关于远程线程注入在这里就不重复讲述了,但是这里需要注意一个问题,那就是CreateRemoteThread()中第6个参数,需要设为CREATE_SUSPENDED,主要参数如下:代码: //4. 创建远程线程 m_hInjecthread = ::CreateRemoteThread(hProcess, //远程进程句柄 NULL, //安全属性 0, //栈大小 (LPTHREAD_START_ROUTINE)LoadLibrary, //进程处理函数 pszDllName, //传入参数 CREATE_SUSPENDED, //默认创建后的状态 NULL); //线程ID3.激活进程中的线程 这里主要用的是ResumeThread()的这个API,需要注意的是先激活主要线程,再激活注入的线程。劫持进程创建注入其实就是远程线程注入的前期加强版,他可以在进程启动前进行注入,由于进程的线程没有启动,这样就可以躲过待注入进程的检测,提高的注入的成功率。
2013年07月02日
80 阅读
0 评论
0 点赞
2013-06-20
2013高考0分作文精华集萃
1. 看到作文题,我陷入了深沉的哲学思考之中,尽管犹太谚语说:“人类一思考,上帝就发笑。”上帝够崇高,能够被他笑,我受宠若惊。 我为什么要跑呢?我跑得过博尔特,跑得过刘翔吗?我跑得过离心力吗?于是我决定自己不再跑,我就站在那里。把中国足球队站成个世界冠军,把信访办的领导站成个信访者,站得半夜来上滩的鲤鱼没有半点柴油味,站得兰城房价下到1千7,站得海枯石烂江水竭,站得小九妹成正房太,站得刘雪华成孙俪、奥巴马成李琦……就这样站个天荒地老,站得自己慢慢变老,也没有什么不好。 我为什么要奔跑呢?因为城管在后面追。我的篮子里也就早上刚摘下的茄子,还带着露水的晶莹,为了少交1块钱的管理费。我篮子里茄子的姐妹,不少没能躲过这些天的雨。3块钱1斤,跑快一点,可以赚得3两333(以下省去无数个3)茄子,因为一篮茄子,也就8块钱。1个穆坞枇杷,抵得上我一篮茄子。一白一紫,差距咋那么大呢?你妹啊!下次我袋里揣个枇杷,一定能跑得更快。据穆坞村书记王茂星说,“浙乡邮礼”活动取得圆满成功。他们正准备把枇杷推向国际市场,穆坞股份准备在纳斯达克上市,发行价每股120元。唉,走神了。只可怜我这把老骨头,硬撑着,总算把那小伙城管甩开了。当然郁闷的还是那小伙子,人家当年还获得过校运会800米的冠军,尽管那学校连带员工,也就百来号人。有歪诗为证:岁月不饶人,肚上肥肉增两圈;3杯白酒两包烟,伤肝伤肺有谁怜?唉,只落得两泪涟涟。 我为什么要鼓掌呢?因为领导在台上讲——领导按掌声来判断人的素养。斯大林时期,每次开会,必得有持续不断的、雷鸣般的掌声。不能轻易停下,偶一疏忽,会被告发。领导怀疑你的忠诚度,毁了你政治前途。多年前的春晚和室内剧,常有莫名其妙的掌声,连鼓掌者都莫名其妙。我曾经的领导不轻易开会,我们这些群众也不轻易鼓掌。偶然有点异味的掌声,领导有的是大智慧,足以对付小聪明。 边奔跑边鼓掌行不行?每天早上,有一小伙子,打着赤膊,边小跑(古文叫趋,小步快走之意,类似于太监的行走方式)边鼓掌。他似乎有些跛脚,一脚深一脚浅,硬是把兰江大桥走得坑坑洼洼。他嘴里喊些什么,我也听不懂。但我知道,他很享受这一过程,从老城走到溪西,又从溪西喊到老城。关于这个人,坊间有多种版本。较为权威的是,因高考压力太大,一连好多年都没能上重点线:他则非重点不读。难道今年的高考作文是为他出的么?因为像他这样既能奔跑、又能鼓掌的太稀少了,比鉴别地沟油的方法还稀少。省考试院的作文题,真的接地气。难怪他这么兴奋,边奔跑,边鼓掌,为了增强感情色彩,还跺脚呢!…… 这样想着,不觉已是自己门前,妻在屋里看《甄嬛传》,儿子在玩《Q宠大乐斗》。虽没有“共剪西窗烛”的浪漫,倒也温馨和谐。我悄悄地对着横山笑了……
2013年06月20日
99 阅读
0 评论
0 点赞
2013-06-14
10步让你成为更优秀的程序员
这篇文章要介绍的,是我作为专业程序员这些年来学到的能真正提高我的代码质量和整体工作效率的10件事情。1. 永远不要复制代码不惜任何代价避免重复的代码。如果一个常用的代码片段出现在了程序中的几个不同地方,重构它,把它放到一个自己的函数里。重复的代码会导致你的同事在读你的代码时产生困惑。而重复的代码如果在一个地方修改,在另外一个地方忘记修改,就会产生到处是bug,它还会使你的代码体积变得臃肿。现代的编程语言提供了很好的方法来解决这些问题,例如,下面这个问题在以前很难解决,而如今使用lambdas却很好实现:代码:/// <summary> /// 一些函数含有部分重复代码 /// </summary> void OriginalA() { DoThingsA(); // unique code DoThingsB(); } /// <summary> /// 另外一个含有部分重复代码的函数 /// </summary> void OriginalB() { DoThingsA(); // 没有重复的代码 DoThingsB(); } 现在我们重构含有部分相同代码的函数,用delegate模式重写它们:代码:/// <summary> /// Encapsulate shared functionality /// </summary> /// <param name="action">User defined action</param> void UniqueWrapper(Action action) { DoThingsA(); action(); DoThingsB(); } /// <summary> /// New implmentation of A /// </summary> void NewA() { UniqueWrapper(() => { // unique code }); } /// <summary> /// New implementation of B /// </summary> void NewB() { UniqueWrapper(() => { // unique code }); }2. 留意你开始分心的时候当你发现自己在浏览facebook或微博、而不是在解决问题,这通常是一种你需要短暂休息的信号。离开办公桌,去喝一杯咖啡,或去跟同事聊5分钟。尽管这样做看起来有点反直觉,但长久去看,它会提高你的工作效率。3. 不要匆忙赶任务而放弃原则当带着压力去解决一个问题或修改一个bug,你很容易失去自制,发现自己匆匆忙忙,甚至完全忘了一直坚持的重要的测试过程。这通常会导致更多的问题,会让你在老板或同事眼里显得很不专业。4. 测试你完成的代码你知道你的代码能做什么,而且试了一下,它确实好用,但你实际上需要充分的验证它。分析所有可能的边界情况,测试在所有可能的条件下它都能如期的工作。如果有参数,传递一些预期范围外的值。传递一个null值。如果可能,让同事看看你的代码,问他们能否弄坏它。单元测试是到达这种目的的常规方法。5. 代码审查提交你的代码之前,找个同事一起坐下来,向他解释你做了哪些修改。通常,这样做的过程中你就能发现代码中的错误,而不需要同事说一句话。这比自己审查自己的代码要有效的多得多。6. 让代码更少如果你发现写了大量的代码来解决一个简单的问题,你很可能做错了。下面的boolean用法是一个很好的例子:代码:if (numMines > 0) { enabled=true; } else { enabled=false; }这时你应该写成这样:enabled = mumMines>0;代码越少越好。这会使bug更少,重构可能性更小,出错的几率更小。要适度。可读性同等重要,你可不能这样做而使代码丧失可读性。7. 为优雅的代码而努力优雅的代码非常的易读,只用手边很少的代码、让机器做很少的运算就能解决问题。在各种环境中都做到代码优雅是很难的,但经过一段时间的编程,你会对优雅的代码是个什么样子有个初步的感觉。优雅的代码不会通过重构来获得。当你看到优雅的代码是会很高兴。你会为它自豪。例如,下面就是一个我认为是优雅的方式来计算多边形面积的方法:代码:static public double GetConvexPolygonArea(Vector2[] vertices) { double area = 0; for (int i = 0; i < vertices.Length; i++) { Vector2 P0 = vertices[i]; Vector2 P1 = vertices[(i + 1) % vertices.Length]; area += P0.Wedge(P1); } return area / 2; }8. 编写不言自明的代码勿庸置疑,注释是编程中很重要的一部分,但能够不言自明的代码跟胜一筹,因为它能让你在看代码时就能理解它。函数名变量名要慎重选择,好的变量/方法名字放到语言语义环境中时,不懂编程的人都能看懂。例如:代码:void DamagePlayer(Player player, int damageAmount) { if (!player.m_IsInvincible && !player.m_IsDead) { player.InflictDamage( damageAmount ); } }自我说明的代码不能代替注释。注释是用来解释“为什么”的,而自我说明的代码是来描述“是什么”的。9. 不要使用纯数字直接把数字嵌入代码中是一种恶习,因为无法说明它们是代表什么的。当有重复时更糟糕——相同的数字在代码的多个地方出现。如果只修改了一个,而忘记了其它的。这就导致bug。一定要用一个命名常量来代表你要表达的数字,即使它在代码里只出现一次。10. 不要做手工劳动当做一系列动作时,人类总是喜欢犯错误。如果你在做部署工作,并且不是一步能完成的,那你就是在做错事。尽量的让工作能自动化的完成,减少人为错误。当做工作量很大的任务时,这尤其重要。11. 避免过早优化当你要去优化一个已经好用的功能代码时,你很有可能会改坏它。优化只能发生在有性能分析报告指示需要优化的时候,通常是在一个项目开发的最后阶段。性能分析之前的优化活动纯属浪费时间,并且会导致bug出现。好吧,我说是10个,但你却得到了额外赠送的一个!这些就是我要说的,我希望它们能帮助你改进编程开发过程。下次再见!祝快乐!Cheers, Paul.
2013年06月14日
110 阅读
0 评论
0 点赞
2013-06-07
图种
概念一种采用特殊方式将图片文件(如jpg格式)与rar文件结合起来的文件。该文件一般保存为jpg格式,可以正常显示图片,当有人获取该图片后,可以修改文件的后缀名,将图片改为rar压缩文件,并得到其中的数据。由于这种方式通常为了一些网友传播种子文件,故称为图种,又叫内涵图。制作方式在线制作图种啦,在线生成图种,操作简便,准备一个文件和图片,按要求提交就可以生成,并且还可以在线选择添加文字进图片里,方便用户知道解压方法,比本地制作方法具有的最大特点,就是在线生成可以附带使用其特有的云反水印技术,可以保证上传到论坛不会被水印损坏,大大提升了图种的存活率和转载率。本地制作首先,需要一些文件与一张图片。把这些文件压缩一下,然后改一个的名字,比如1.rar。假设图片的名字为2.jpg。然后,把两个文件放进一个硬盘,为了简单,推荐放进根目录,比如我们放进E盘。方法一:调出运行框:开始---运行--CMD在光标所在地方输入 copy /b E:2.jpg+E:1.rar E:output.jpg 然后回车。(注意空格与半角全角,建议粘贴复制)然后:会出现:”E:2.jpgE:1.rar已复制 1 个文件。这样就完成了文件的合并。将jpg文件与rar文件合并起来了。(注意如果图片2格式是jpeg,则需在上述命令输入jpeg,否则会出现找不到指令文件),合并后的文件在E盘,名字为output.jpg我们把这个图片由.jpg改成.rar结尾以后可以发现仍然可以解压缩得到我们的文件,改成jpg依然是一张图片。方法二:1.新建文件夹。 2.在文件夹里,新建文本文档 3.输入 copy/b 2.jpg+1.rar %cd%\output.jpg (注意空格与半角全角,建议粘贴复制) 其中图片与压缩包名不能改“output”可改。 4.保存,改文件格式 .txt 为 .bat。 5.将1.jpg和1.rar都放置在bat文件所在文件夹,运行。 6.会在bat文件所在文件夹内生成output.jpg若是认为这种方式还是太过麻烦,可使用可用的图种制作软件。例如:“jpg,rar转换器”等等。操作简单但不支持批量生产,并且对文件类型有严格要求。操作方法1.打开程序。2.打开文件目录选中目标jpg文件。3.打开文件目录选中目标rar文件。4.选择合成图片输出路径,输入文件名。5.点击合成文件。现在网上流传一个叫“内涵图批量制作工具”的小程序,支持文件拖放、批量合并、记忆输出目录,大家可以去试试。制作原理简单的说就是把图片与rar文件用二进制的方式合并起来。图片的读取只需要读取前半部分的数据即可以正常显示,rar压缩文件只需要读取后半部分的数据即可以正常读取。
2013年06月07日
87 阅读
2 评论
0 点赞
2013-06-07
超帅的自动换IP工具
改电脑的虚拟IP是很简单的事,有图形介面的设定,有用批处理快速更改IP地址,但对于电脑小白而言,这工具也蛮方便的。 {anote icon="fa-download" href="http://pan.baidu.com/share/link?shareid=3139627584&uk=1547026424" type="success" content="下载地址"/}
2013年06月07日
102 阅读
2 评论
0 点赞
2013-06-07
云计算核心技术
云计算技术有以下一些优越性: 1、规模大。2、虚拟化。3、高可靠性。3通用性强。4、高的伸缩性。5、它是按需服务的。6、及其的廉价。今天给大家分享一个有关云计算的核心技术的一本教材,本人感觉还不错,看着呢,大家喜欢的可以拿去看看。
2013年06月07日
63 阅读
0 评论
0 点赞
2013-06-07
木马后门检测工具包
作为玩黑的,一定要有被“黑”的心理准备和被黑后的“报复”手段。为此,量身打造的“木马后门检测工具”将是你的利器,后续会针对破解及原理陆续放出文章。
2013年06月07日
94 阅读
0 评论
0 点赞
2013-05-27
用vb写的比sobig更毒的蠕虫病毒!!!
代码如下:
2013年05月27日
89 阅读
0 评论
0 点赞
1
...
20
21
22
...
24