Rise的自留地

记录生活中的点滴,分享编程技术和游戏开发经验。

0%

点这里下载示例代码

实现文件自删除不是一个特别新的话题了,不过貌似一直没有特别完美的解决方式。从早先Gary Nebbett的堆栈溢出版本到后来的批处理、临时文件等方式,无不存在着各样瑕疵:如堆栈溢出不支持XP,临时文件(批处理)不够优雅等等。

当然,还有用驱动发IRP的方式,不过这只是一个自删除,杀鸡焉用牛刀?于是这个方案在我这儿亦不讨论。

李马讨论的,只是一个2005年的老调重提:远线程注入。2005年李马提到的DLL远程注入技术只是远线程的最简单应用,局限很多,能做的事情很少;下面的自删除示例,则是如何让远线程能够做更多的事,也可以说是一个补充材料,不必记入原创文档了吧就。

言归正传。首先,我们假定这个线程函数是这样的:

DWORD WINAPI DelProc(LPVOID lpParam)
{
    Sleep(50);
    DeleteFileA((LPCSTR)lpParam);
return 0;
}

解释一下,先用Sleep等待要删除的程序结束,之后调用DeleteFile删除目标文件。

现在,你可以在VC的Project Settings->C/C++->Category: Listing Files->Listing file type中,设置输出文件的类型为“Assembly, Machine Code, and Source”或“Assembly with Machine Code”,这样就会在编译完成后生成带有汇编代码和指令机器码的附属文件供你下一步对照。——当然,如果你极熟悉汇编,这一步可以跳过。

在查看附属文件后,我们可以提取出对我们有用的汇编代码:

push 50
call Sleep
mov  eax, [esp + 4]
push eax
call DeleteFileA
ret  4

之后,对照着对应的机器码,构造下面的结构:

#pragma pack(push, 1)
typedef struct _tagDeleteStruct {
    BYTE  byPush;
    DWORD dwTime;
    BYTE  wCall1;
    DWORD dwSleep;
    DWORD dwMov;
    BYTE  byPushEax;
    BYTE  wCall2;
    DWORD dwDeleteFileA;
    BYTE  byRet;
    WORD  w4;
    CHAR  szFile[1];
} DELETESTRUCT, *PDELETESTRUCT;
#pragma pack(pop)

最后的szFile域,就是用来放置文件名的。其余的就不解释了,因为下面就要填充它了。远线程函数还是很模式化的代码,改造自两年前我的RemoteLoadLibrary:

BOOL RemoteDel(DWORD dwProcessID, LPCSTR lpszFileName, DWORD dwTime)
{
// 打开目标进程
    HANDLE hProcess = OpenProcess(
        PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE,
        dwProcessID);
if (NULL == hProcess)
return FALSE;
// 向目标进程地址空间写入删除信息
    DWORD         dwSize = sizeof(DELETESTRUCT) + lstrlenA(lpszFileName);
    PDELETESTRUCT pDel   = (PDELETESTRUCT)GlobalAlloc(GPTR, dwSize);
    HMODULE hKernel32 = GetModuleHandle(_T("kernel32.dll"));
// push dwTime
    pDel->byPush = 0x68;
    pDel->dwTime = dwTime;
// call Sleep
    pDel->wCall1  = 0xe8;
    pDel->dwSleep = (DWORD)GetProcAddress(hKernel32, "Sleep");
// mov  eax, [esp + 4]
    pDel->dwMov = 0x0424448b;
// push eax
    pDel->byPushEax = 0x50;
// call DeleteFileA
    pDel->wCall2        = 0xe8;
    pDel->dwDeleteFileA = (DWORD)GetProcAddress(hKernel32, "DeleteFileA");
// ret  4
    pDel->byRet = 0xc2;
    pDel->w4    = 0x0004;
    lstrcpyA(pDel->szFile, lpszFileName);
    LPVOID lpBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT,
        PAGE_READWRITE);
if (NULL == lpBuf)
    {
        GlobalFree((HGLOBAL)pDel);
        CloseHandle(hProcess);
return FALSE;
    }
// 修正近调用
    pDel->dwSleep       -= (DWORD)lpBuf + offsetof(DELETESTRUCT, dwMov);
    pDel->dwDeleteFileA -= (DWORD)lpBuf + offsetof(DELETESTRUCT, byRet);
    DWORD dwWritten;
    WriteProcessMemory(hProcess, lpBuf, (LPVOID)pDel, dwSize, &dwWritten);
// 创建线程,远程删除!
    DWORD dwID;
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
        (LPTHREAD_START_ROUTINE)lpBuf,
        (LPVOID)((DWORD)lpBuf + offsetof(DELETESTRUCT, szFile)), 0, &dwID);
    GlobalFree((HGLOBAL)pDel);
    CloseHandle(hThread);
    CloseHandle(hProcess);
return TRUE;
}

至于为什么最后不用VirtualFreeEx释放资源,那是因为注入的远程代码在执行的时候目标exe就已经消失了,所以这里的寄主程序肯定存在着内存泄露,真是造孽啊。

最后说三点。第一,RemoteDel是要挑选一个寄主程序的,这个程序应该始终运行并存在于当前的系统中,我在示例中挑选的是explorer.exe;并且,打开这个进程是需要调试权限的,提权的代码也一并加入在示例代码中,算是弥补了2005年的缺失。第二,为了方便定位,我修改了远程代码中的调用,也就是call ds:xxx(FF 15 xxx)改为了call near xxx(E8 xxx)。第三,自己手写机器码的做法的确不如纯汇编代码重定位来的优雅,但是我认为这里填充并定位Sleep和DeleteFile的片断也是纯汇编的办法无法比拟的。

游戏要实现模型的突出显示,最好是边缘高亮的效果.刚听到这个东西时,第一个进入头脑中的就是:边缘检测.于是就写了一个:
<tbody>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div>Pass 0:</div>

        <div>渲染模型到一个RenderTarget Model上,并把模型的形状写入Alpha通道.</div>

        <div>Pass 1:</div>

        <div>对上面得到的Alpha通道用拉普拉斯模板进行滤波,得到一个边缘,写入另一个RenderTarget Edge.</div>

        <div>Pass 2:</div>

        <div>把前面得到的两个RenderTarget进行合成,输出到屏幕.</div>

        </td>

    </tr>

</tbody>
 
虽说效果还不错,但是用掉了两个RenderTarget,显然不合算.而且,用拉普拉斯在PixelShader中进行逐像素的处理,效率并不高.
 
阿来在GameDev上求得另一种方法:把模型画两遍,其中一次对模型进行一次放大,关闭Z-Write就出来这种效果了.不过有两个问题:
一是模型直接放缩是以模型坐标系的原点来的,而这个原点并不一定是在模型的中心.就算在中心,对于一些非凸多面体并不能得到很好的效果,有一些边缘会被模型遮住.
二是,关闭了深度检测,那这个模型怎么跟别的模型来进行遮挡处理呢?
 
后来在群里有人提醒说在3D游戏程序设计入门这本书上有,我才想起来有一个卡通渲染的例子.卡通渲染?那里面不也有轮廓生成吗?看了一下书上的实现方法,用的是三角形退化,有点复杂.于是google之,发现了一个跟GameDev上那个方法差不多思想的:
<tbody>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div>Pass0:</div>

        <div>把模型按法线方向进行放大,然后渲染成单色模型,不过只渲染背面,避免遮住正常的模型.(把D3DRS_CULLMODE设成D3DCULL_CW就可以了)</div>

        <div>Pass1:</div>

        <div>正常渲染模型,不用做什么改变.不过不要忘了把D3DRS_CULLMODE改回来.</div>

        </td>

    </tr>

</tbody>
 
Shader:
<tbody>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div><span style="color: blue">float4x4</span> matViewProjection;</div>

        <div>&nbsp;</div>

        <div><span style="color: blue">struct</span> VS_INPUT </div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; <span style="color: blue">float4</span> Position : <span style="color: fuchsia">POSITION0</span>;</span></div>

        <div style="margin-left: 21pt; text-indent: -21pt"><span>&nbsp;&nbsp; <span style="color: blue">float3</span> Normal&nbsp;&nbsp; : <span style="color: fuchsia">NORMAL0</span>;</span></div>

        <div>};</div>

        <div>&nbsp;</div>

        <div><span style="color: blue">struct</span> VS_OUTPUT </div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; <span style="color: blue">float4</span> Position : POSITION0;</span></div>

        <div>};</div>

        <div>&nbsp;</div>

        <div>VS_OUTPUT vs_main( VS_INPUT Input )</div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; VS_OUTPUT Output;</span></div>

        <div>&nbsp;</div>

        <div style="margin-left: 21pt; text-indent: -21pt"><span>&nbsp;&nbsp; Output.Position = <span style="color: blue">float4</span>(Input.Position.xyz + Input.Normal*0.4f,1);</span></div>

        <div><span>&nbsp;&nbsp; Output.Position = <span style="color: red">mul</span>( Output.Position, matViewProjection );</span></div>

        <div>&nbsp;</div>

        <div style="margin-left: 21pt; text-indent: -21pt"><span>&nbsp;&nbsp; <span style="color: blue">return</span>( Output );</span></div>

        <div>}</div>

        </td>

    </tr>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div><span style="color: blue">sampler2D</span> BaseMap;</div>

        <div>&nbsp;</div>

        <div><span style="color: blue">float4</span> ps_main() : <span style="color: fuchsia">COLOR0</span></div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; <span style="color: blue">return</span> <span style="color: blue">float4</span>(0, 1, 0, 1);</span></div>

        <div>}</div>

        </td>

    </tr>

</tbody>
 
下面是两种方法实现的效果对比:
差不多哈,区别就是用卡通渲染的那种方法出来的中间也有轮廓线.
 

a

original address: http://blog.csdn.net/starflash2003/archive/2004/10/13/135493.aspx


强制类型转换

为了有助于着色器的编写和所产生代码的效率,最好熟悉一下HLSL的强制类型转换机制。强制类型转换常用于扩展或缩减选定的变量以匹配要赋值的变量。例如,在下列例子中,初始化vResult时把float型常量0.0f强制转换为 float4型{0.0f , 0.0f , 0.0f , 0.0f }。

original address: http://blog.csdn.net/starflash2003/archive/2004/10/09/130020.aspx


语言基础

现在你已经对什么是HLSL顶点和像素着色器以及他们如何与低层汇编着色器相互作用有了了解,我们将讨论一些语言本身的细节。

关键字

关键字是HLSL语言保留的预定义标识符,不能在你的程序中作为标识符使用。标有'*'的关键字不区分大小写。

original address: http://blog.csdn.net/starflash2003/archive/2004/10/08/128688.aspx


引言

高层着色语言(HLSL)是DirectX® 9最为强力的新组件之一。使用这种标准的高级语言, 在进行着色时编写者可以专注于算法而不用再去理会诸如寄存器的分配,寄存器读端口限制, 并行处理指令等等硬件细节. 除了把开发者从硬件细节中解放出来之外,HLSL 也具有高级语言所有的全部优势,诸如:代码重用容易, 可读性增强以及存在一个优化过的编译器。本书和 ShaderX2 - Shader Tips & Tricks 这本书的许多章节就用到了HLSL编写的着色器. 阅读完本章引言后,你会很容易理解那些着色器并在工作中用到它们。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
NTSTATUS KeWaitForSingleObject(
    IN PVOID Object,
    IN KWAIT_REASON WaitReason,
    IN KPROCESSOR_MODE WaitMode,
    IN BOOLEAN Alertable,
    IN PLARGE_INTEGER Timeout OPTIONAL   // Pointer to a time-out value that specifies the absolute or relative time, in 100 nanosecond units, 
    );


VOID KeStallExecutionProcessor(
    IN ULONG MicroSeconds                    // </em>Specifies the number of microseconds to stall.
    );

BOOLEAN KeSetTimer(
    IN PKTIMER Timer,
    IN LARGE_INTEGER DueTime, // Specifies the absolute or relative time at which the timer is to expire. If the value of the <em>DueTime</em> parameter is negative, the expiration time is relative to the current system time. Otherwise, the expiration time is absolute. The expiration time is expressed in system time units (100-nanosecond intervals). Absolute expiration times track any changes in the system time; relative expiration times are not affected by system time changes. 
    IN PKDPC Dpc OPTIONAL
    );

为了重复地调用CustomTimerDpc例程,使用KeSetTimerEx来设置定时器,并在Period参数中规定一个再次发生的间隔。除了这个附加的参数,KeSetTimerEx就象KeSetTimer一样。

卡巴主动防御中检测隐藏进程的方法:

    Hook掉系统的SwapContext,这种方法是在2003年被提出的;这个函数被KiSwapThread调用,负责线程调度;下面这部分代码就是卡巴Detour SwapContext的汇编代码的分析(后面附上对应的c代码):

去年年底帮别人做一个项目,了解了一下TCPMP,觉得这个软件的结构写得很好就做了些记录,今天偶然翻出来看看觉得可能对正在研究这个软件的人有点帮助就贴出来。如果转载请注明出处,谢谢。

TCPMP是一个功能强大开放式的开源多媒体播放器,
播放器主要由核心框架模块(common工程)和解码器分离器插件组成。
TCPMP
的插件非常多,、libmad我们联合几个最常用的插件(ffmpegsplitter)来说明,其中interface插件实现TCPMP的界面,由于他和媒体播放没有什么关系,这部分可以完全被替换掉,替换成自己的界面。
ffmpeg
工程是系统主要的音视频解码模块,ffmpeg是一个集录制、转换、音/视频编码解码功能为一体的完整的开源解决方案。FFmpeg的开发是基于Linux操作系统,但是可以在大多数操作系统中编译和使用。ffmpeg支持MPEGDivXMPEG4AC3DVFLV40多种编码,AVIMPEGOGGMatroskaASF90多种解码。很多开源播放器都用到了ffmpeg。但是ffmpeg程序解码效率不是很高,系统仅仅使用了FFmpeg的部分解码功能。
ffmpeg
主目录下主要有libavcodeclibavformatlibavutil等子目录。其中libavcodec用于存放各个encode/decode模块,libavformat用于存放muxer/demuxer模块,libavutil用于存放内存操作等常用模块。本系统的媒体文件分离器有单独的splitter模块完成所以不需要libavformat子目录。ffmpeg目录下libavcodeclibavutil保留子目录。

“熊猫烧香”余波未了,“灰鸽子”又飞进了人们的视野。

  在这个领域,互联网“险情”不断。

  ——网络世界,这个表面看起来风平浪静的生态,背后无时不在发生着弱肉强食的事件,就像森林里生物链一样默默发生着变化,而外边望去却一片平静。