我正在开发一个似乎有漏洞的C#应用程序.我用过内存分析器,发现我的
私有字节不断增加,但所有堆中的字节数不会增加,这意味着它可能是本机内存泄漏
现在我卡住了,如何在本机代码中发现内存泄漏?
为什么语音识别如此困难?涉及的具体挑战是什么?我已经阅读了一个关于语音识别的问题,这个问题部分回答了我的一些问题,但答案主要是轶事而不是技术问题.它仍然没有真正回答为什么我们仍然不能在这个问题上投入更多的硬件.
我已经看到使用神经网络和环境FFT分析执行自动降噪的工具,效果很好,所以我看不出为什么我们仍然在努力解决噪音,除非在诸如可笑的大声背景噪音或多个语音源等困难情况下.
除此之外,是不是只是使用非常大,复杂,训练有素的神经网络进行处理,然后投入硬件以使其足够快地工作?
我知道强烈的口音是一个问题,我们都有口语,但当这个人用缓慢而清晰的美国或英国口音说话时,这些识别引擎仍然会弄错.
那么,这笔交易是什么?有哪些技术问题使计算机仍然难以理解我?
我花了最后一小时解决C#中非托管内存的奇怪问题.
首先,一点背景.我有一个C#DLL导出一些本机方法(通过这个很棒的项目模板),然后由Delphi应用程序调用.其中一个C#方法必须将结构传递回Delphi,然后将其转换为记录.我已经可以告诉你感到恶心,所以我不再详细介绍了.是的,这很难看,但替代方案是COM ......不,谢谢.
以下是有问题的代码的简化:
IntPtr AllocBlock(int bufferSize)
{
IntPtr ptrToMem = Marshal.AllocHGlobal(bufferSize);
// zero memory
for(int i = 0; i < bufferSize; i++)
Marshal.WriteInt16(ptrToMem, i, 0);
return ptrToMem;
}
Run Code Online (Sandbox Code Playgroud)
实际上,这里有一些其他的东西,与本机资源跟踪相关,但基本上就是这样.如果你已经发现了这个bug,做得好.
本质上,问题在于我使用WriteInt16而不是WriteByte由于智能感知辅助的拼写错误导致最后一次迭代在缓冲区末尾写入一个字节.我想是容易犯的错误.
然而,在调试器中谚语的这种痛苦使得它在调试器中无声地失败,并且应用程序的其余部分继续工作.内存已经分配,除了最后一个字节之外的所有字节都是零,所以它工作正常.在调试器外部启动时,它会导致应用程序因访问冲突而崩溃.经典的Heisenbug情况 - 当您尝试分析它时,该错误消失了.请注意,此崩溃不是托管异常,而是真正的CPU级访问冲突.
现在,这让我感到困惑有两个原因:
连接任何调试器时都没有抛出异常 - 我尝试了Visual Studio,CodeGear Delphi 2009和OllyDbg.附上后,该程序运作良好.没有附加时,程序崩溃了.所有尝试都使用了完全相同的可执行文件.我的理解是,调试不应该改变应用程序的行为,但它显然是这样做的.
通常情况下,我希望此操作AccessViolationException在我的托管代码中导致,但它会因内存访问冲突而死亡ntdll.dll.
现在,公平地说,我的案例可能是C#历史上最模糊(也可能是错误的)角落案例之一,但我对于如何连接任何调试器来防止崩溃感到迷茫.我特别感到惊讶的是它在OllyDbg下运行,它不会像Visual Studio那样干扰任何接近的过程.
那么,到底发生了什么?为什么在调试期间吞下(或不引发)异常,而不是在调试器之外?当我试图Marshal.WriteInt16在分配的内存块之外调用时,为什么没有抛出托管访问冲突异常,因为文档说它应该?
我们都知道,制作一个没有一两个缺陷的大型网站几乎是不可能的.因此,我编写了一个小型监视器,用于检查Apache访问日志是否存在潜在的SQL注入攻击(以及其他内容),并且它运行良好.每当有人尝试攻击时我都会收到警报,而且我的误报很少,以至于默认操作现在将它们转储到iptables下拉列表中.它甚至帮助我识别了一些(非安全性)错误并将其删除.
这是我的规则(不区分大小写):
PathInjection = \./\.\./(bin|boot|data|dev|etc|home|lib|lib64|media|mnt|opt|proc|root|sbin|selinux|srv|sys|tmp|usr|var)/
Havij = 0x31303235343830303536
r3dm0v3 = 0x7233646D3076335F68766A5F696E6A656374696F6E
LogicBypass = '.*?(\bor|\band|\bxor|\|\||\&\&).*?--
UnionSelect = union[^a-z-_]+((all|distinct)[^a-z-_]+)?select[^a-z-_]
Run Code Online (Sandbox Code Playgroud)
我想知道的是,您如何绕过这些检查并仍能产生有效注射?你能想出一种在不引入误报的情况下改进它们的方法吗?
几点说明:
编辑:
好的,所以人们似乎误解了我的意图.这可能是我的错,因为我没有完全解释.这被要求作为监控产品的附加功能,旨在提供最低限度的安全监控.作为我们与客户和文档对话的一部分,我们强调这不是一个包罗万象,也不是适当的安全基础设施(例如IDS和防火墙)的替代品.它只是一种信息服务,可帮助提供基本威胁检测并生成有关潜在攻击数量的统计信息.我不是想写一个IDS或防火墙.如果由我决定,我会退出该功能并告诉他们使用自己的监控系统安装一整套安全基础设施,但这不是我的号召.目前的情况是我一直在自己的网站上测试系统.现在,我只是想找到一种方法来改进正则表达式字符串,使其更有效.希望这可以解决一些问题.
我正在研究一个x86 asm混淆器,它将英特尔语法代码作为字符串,并输出一组混淆的等效的操作码.
这是一个例子:
mov eax, 0x5523
or eax, [ebx]
push eax
call someAPI
Run Code Online (Sandbox Code Playgroud)
变成这样的东西:
mov eax, 0xFFFFFFFF ; mov eax, 0x5523
and eax, 0x5523 ;
push [ebx] ; xor eax, [ebx]
or [esp], eax ;
pop eax ;
push 12345h ; push eax
mov [esp], eax ;
call getEIP ; call someAPI
getEIP: ;
add [esp], 9 ;
jmp someAPI ;
Run Code Online (Sandbox Code Playgroud)
这只是一个例子,我没有检查过这不会搞砸标志(它可能会).
现在我有一个XML文档,列出了指令模板(例如push e*x)和可以使用的替换指令列表.
我正在寻找的是一种自动生成操作码序列的方法,该操作码产生与输入相同的结果.我不介意做一个受过良好教育的强盗,但我不确定我是怎么做到的.
我正在为一个我无法改变的协议编写一个用于interop的结构类型的自定义序列化器.我正在使用反射来提取结构成员值并将它们写入a BinaryWriter.它仅用于支持基本类型和数组.
if (fi.FieldType.Name == "Int16") bw.Write((Int16)fi.GetValue(obj));
else if (fi.FieldType.Name == "UInt16") bw.Write((UInt16)fi.GetValue(obj));
else if (fi.FieldType.Name == "Int32") bw.Write((Int32)fi.GetValue(obj));
else if (fi.FieldType.Name == "UInt32") bw.Write((UInt32)fi.GetValue(obj));
else if (fi.FieldType.Name == "Int64") bw.Write((Int64)fi.GetValue(obj));
else if (fi.FieldType.Name == "UInt64") bw.Write((UInt64)fi.GetValue(obj));
else if (fi.FieldType.Name == "Single") bw.Write((float)fi.GetValue(obj));
else if (fi.FieldType.Name == "Double") bw.Write((double)fi.GetValue(obj));
else if (fi.FieldType.Name == "Decimal") bw.Write((decimal)fi.GetValue(obj));
else if (fi.FieldType.Name == "Byte") bw.Write((byte)fi.GetValue(obj));
else if (fi.FieldType.Name == "SByte") bw.Write((sbyte)fi.GetValue(obj));
else if (fi.FieldType.Name == "String") bw.Write((string)fi.GetValue(obj));
Run Code Online (Sandbox Code Playgroud)
显然这是丑陋的,当我想对这些类型的数组做同样的事情时,它变得更加难看.
如果我可以做这样的事情,那将是非常好的:
bw.Write( (fi.FieldType) fi.GetValue(obj) ); …Run Code Online (Sandbox Code Playgroud) 任务:
我正在构建一组x86汇编逆向工程挑战,其中我已经完成了大约20个左右.他们只是为了娱乐/教育.
当前的挑战是更先进的挑战之一,并且涉及一些技巧,使得它看起来像EP实际上在正常程序中,但它实际上被包装在另一个PE部分中.
继承人的基本流程:
这个想法是因为他们认为他们处于正常的程序流程中,这使得他们错过了反调试和后来的检查.无论如何,一切正常.
问题:
目前的问题是,OllyDbg和其他一些工具会查看打包部分并发现它具有较高的熵,并发出一个警告,说它已经打包了.PE头中的代码段指针是正确设置的,所以它不会从EP外部代码中得到它 - 它纯粹是一个熵分析的东西.
题:
有没有我可以使用的加密方法保留低熵,但仍然很容易在x86 asm中实现?我不想使用普通的xor,因为它太容易了,但我也不希望它像包装一样抓住它并让游戏消失.
我想到了一个类似洗牌器的东西(以某种方式生成一个密钥流并使用它来交换4字节的代码块),但我不确定这是否会起作用,甚至是简单的.
有人有任何想法吗?
从MSDN文档Marshal.AllocHGlobal:
AllocHGlobal是Marshal类中的两种内存分配方法之一.此方法从Kernel32.dll公开Win32 LocalAlloc函数.
考虑到有一个GlobalAlloc API在全局堆上而不是本地堆上分配内存,这个方法的名称不是误导吗?
是否有理由将其命名AllocHGlobal,而不是AllocHLocal?
更新: Simon在评论中指出,Windows中不再存在全局堆这样的东西,并且这些GlobalAlloc和LocalAllocAPI仅用于遗留目的.这些天,GlobalAllocAPI不再是一个包装器了LocalAlloc.
这解释了为什么API根本不调用GlobalAlloc,但它没有解释为什么API在AllocHGlobal没有(不能)使用全局堆时也被命名,甚至也没有调用GlobalAlloc.命名不可能是出于遗留原因,因为在删除16位支持之后,直到.NET 2.0才会引入命名.所以,问题仍然存在:为什么Marshal.AllocHGlobal如此误导性地命名?
如果在Windows计算器中输入1.0000000000000000000000000000001,然后重复点击阶乘(n!)按钮,会得到一些奇怪的结果:
1.0000000000000000000000000000001 [n!]
1 [n!]
1 [n!]
1 [n!]
0.9999999999999999999999999999997 [n!]
0.9999999999999999999999999999998 [n!]
0 [n!]
1
Run Code Online (Sandbox Code Playgroud)
自己尝试一下 - 这很奇怪!
我的主要兴趣是为什么我们在倒数第二步得到零.IEEE浮动的人工制品会导致这些问题吗?
我正在尝试将原始二进制数据从线程上下文转换为人类可读的格式,并且在尝试将四倍精度浮点值转换为C#中的可读格式时出现空白.
最后,我想用标准科学记数法显示它,例如1.234567×10 89.我并不担心过程中精度的损失 - 我只是想要了解价值是什么.
我的第一个想法是通过提高指数手动计算值为double,但当然在很多情况下我会超过最大值.我不介意失去精确度,但根本无法显示它是不可接受的.
我可以使用某种简单的数学黑客吗?
c# ×5
assembly ×2
ieee-754 ×2
marshalling ×2
x86 ×2
.net ×1
algorithm ×1
automation ×1
casting ×1
debugging ×1
dynamic ×1
encryption ×1
math ×1
memory ×1
memory-leaks ×1
obfuscation ×1
php ×1
pinvoke ×1
regex ×1
security ×1
sql ×1
theory ×1
winapi ×1
windows ×1