zl程序教程

您现在的位置是:首页 >  后端

当前栏目

[原创]C# 与 汇编 的一次亲密接触。

c# 一次 原创 汇编 接触
2023-09-14 08:56:51 时间

废话不讲,转入正题!

前不久,有位网友在MSN上问我:如何解除被独占打开文件的锁定?
虽然从ring0层可以做到更加Power的处理,但是相对繁琐。
权衡之后,我决定在ring3层解决这个问题。经过网上的一番搜
索之后,写了一个简单的exe程序。后来略觉"简陋",遂决定加上
GUI。写win32界面不是汇编的强项,于是决定用.Net中的C#来写。

C#的高级语法对于数值运算、字符串、图形界面的处理简单方便;
而汇编对于程序性能优化、体积精简、低层代码可控性又得心应手。
两者结合使用,可以达到扬长避短的作用。和以前我用VB   +   ASM
的花哨界面不同,这次我力图做到界面最精简(当然还是有点花哨,呵呵)
,先做一个DEMO,由于才学C#不久,加上水平有限,可能有很多纰漏和
错误,以及一些还可以优化的地方,希望各位不吝指出,多谢了。

截图:

 

 

 

 

 

 

[细节 要点]

由文件句柄得到文件的名称,还可以用内存影射文件的方法,但有局限性。

Assembly code

    _GetFileNameByHandle proc uses esi edi ebx _handle,_hProcess,/
    _lpFileName,/
    _lpProcessName
    ;_lpstOpenFile

    local @stFI:_FileInfo,@hThread:dword

    mov eax,_handle
    mov @stFI.Handle,eax

    invoke RtlZeroMemory,addr @stFI.FInfo.FileNameW,/
    MAX_PATH * 2

    invoke CreateThread,NULL,0,addr _WorkThread,/
    addr @stFI,0,NULL
    mov @hThread,eax

    invoke WaitForSingleObject,@hThread,100

    .if eax == WAIT_TIMEOUT
    invoke TerminateThread,@hThread,0
    .endif

    invoke CloseHandle,@hThread

    invoke RtlZeroMemory,addr buf,/
    sizeof buf

    invoke GetProcessImageFileNameA,_hProcess,addr buf,/
    sizeof buf

    invoke _GetProcessShortName,addr buf

    invoke lstrcpy,_lpProcessName,addr buf

    mov eax,@stFI.FInfo.FileNameLength

    .if eax != 0
    push eax

    invoke RtlZeroMemory,addr buf,/
    sizeof buf

    pop eax
    shr eax,1

    invoke WideCharToMultiByte,CP_ACP,0,/
    addr @stFI.FInfo.FileNameW,eax,/
    addr buf,MAX_PATH,NULL,NULL

    invoke lstrcpy,_lpFileName,addr buf
    .else
    invoke lstrcpy,_lpFileName,addr szDefaultFileName
    .endif

    ret

    _GetFileNameByHandle endp


有些"文件"(实际是管道)会造成操作挂起,遂用线程处理之:

Assembly code


    _WorkThread proc _lpFileInfo
    local IoStatus:IO_STATUS_BLOCK

    assume esi:ptr _FileInfo
    mov esi,_lpFileInfo

    invoke NtQueryInformationFile,[esi].Handle,addr IoStatus,/
    addr [esi].FInfo,sizeof(_FileInfo)-sizeof(dword),/
    FileNameInformation

    assume esi:nothing
    ret

    _WorkThread endp

关于C#与汇编的接口兼容问题,取出一个结构说明:
在C#中:

C# code



    private struct _stOpenFile
    {
    public uint lpProcessName;
    public uint lpFileName;
    public uint ProcessID;
    public uint Flags;
    public uint hFile;
    public uint GrantedAccess;
    }



在   asm   中:

Assembly code



    _stOpenFile struct

    lpProcessName dd ?
    lpFileName dd ?
    ProcessID dd ?
    Flags dd ?
    hFile dd ?
    GrantedAccess dd ?
    _stOpenFile ends



在C#中调用方法:

C# code


    private void btnFind_Click(object sender, EventArgs e)
    {
    StringBuilder szTmp = new StringBuilder(256);

    string FileName, ProcessName;

    _stOpenFile stOP = new _stOpenFile();

    this.btnFind.Enabled = false;

    this.lstvewFind.Items.Clear();
    this.lstvewFind.Refresh();

    unsafe
    {
    byte[] szProcessName = new byte[256];
    byte[] szFileName = new byte[256];

    fixed (byte* lpPN = szProcessName)
    fixed (byte* lpFN = szFileName)
    {
    stOP.lpProcessName = (uint)lpPN;
    stOP.lpFileName = (uint)lpFN;

    while (EnumAllOpenFile(ref stOP) == true)
    {
    ProcessName = Encoding.Default.GetString(szProcessName).Trim(/0);
    FileName = Encoding.Default.GetString(szFileName).Trim(/0);

    if ((FileName.ToString().Length == 0) (ProcessName.ToString().Length == 0))
    {
    Array.Clear(szProcessName, 0, 256);
    Array.Clear(szFileName, 0, 256);
    continue;
    }

    if (FileName.ToString().ToLower() == this.txtFind.Text.ToString().ToLower())
    {
    this.lstvewFind.Items.Add(ProcessName.ToString()).SubItems.AddRange(new string[] {
    FileName.ToString(),stOP.hFile.ToString(),stOP.Flags.ToString(),
    "0x"+Convert.ToString(stOP.GrantedAccess,16),stOP.ProcessID.ToString()});
    this.lstvewFind.Refresh();
    }
    else
    {
    szTmp.Remove(0, szTmp.Length);
    szTmp.Append(FileName.ToString());
    GetShortName(szTmp);
    if (szTmp.ToString().ToLower() == this.txtFind.Text.ToString().ToLower())
    {
    this.lstvewFind.Items.Add(ProcessName.ToString()).SubItems.AddRange(new string[] {
    FileName.ToString(),stOP.hFile.ToString(),stOP.Flags.ToString(),
    "0x"+Convert.ToString(stOP.GrantedAccess,16),stOP.ProcessID.ToString()});
    this.lstvewFind.Refresh();
    }
    }
    Array.Clear(szProcessName, 0, 256);
    Array.Clear(szFileName, 0, 256);
    }
    }
    }
    MessageBox.Show("Total Find " + lstvewFind.Items.Count.ToString() + " Open Files !");

    this.btnFind.Enabled = true;
    }

    上面应该可以再大幅度优化,请各位不吝指出,多谢。






如何写好高质量的原创文章? 随着百度算法的不断升级,百度越来越重视原创文章了,但是原创文章可不单单是用工具查询的相似度为0的文章,更多的应当是可以解决用户需求,能够引发用户阅读兴趣的文章,即看了这篇文章还想下次再来你的网站进行学习。
一个网站的好坏,能否有好的排名,跟网站的内容的好坏是有直接的关系的,正所谓“内容为王,外链为皇”,SEO的排名是以页面为单位的,需要足够的内容来支撑,有高质量的内容的页面才会被百度收录,能被百度收录对应的页面关键词才会有排名,关键词有排名网站才会产生流量。
汇编学习 地址总线 地址总线宽度决定访问内存的大小 例如8086架构可以有20 个地址总线 一个地址总线为2个字节 2个2位的16进制  可以访问的最大内存我2^20 也就是1m  最大可以装在内存为1mb 数据总线决定数据吞吐量 8086 的数据总线为16  每次数据吞吐量也就是2个字节 ...
《C语言程序设计》一 1.2 简单的C语言程序 本节书摘来自华章出版社《C语言程序设计》一 书中的第1章,第1.2节,作者:赵宏 陈旭东 马迪芳,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
对X86汇编的理解与入门 本文描述基本的32位X86汇编语言的一个子集,其中涉及汇编语言的最核心部分,包括寄存器结构,数据表示,基本的操作指令(包括数据传送指令、逻辑计算指令、算数运算指令),以及函数的调用规则。个人认为:在理解了本文后,基本可以无障碍地阅读绝大部分标准X86汇编程序。