Buffer Overflows in Regmon Traces

原创 2007年09月14日 03:33:00
Last time I talked about buffer overflow errors that you might see in Filemon traces. Now I’ll turn my attention to the same errors, but in Regmon traces. Recall that a buffer overflow error in this context is not a security hole, but a way for the system to tell an application that there’s more data available in response to a query the application has made than can fit in the application’s output buffer. A commenter on the previous post pointed out that a better error for this case would be “buffer too small” or “more data available”, and I agree. There is in fact a STATUS_BUFFER_TOO_SMALL error code, but it’s used in situations where no data is copied to the caller’s buffer, whereas STATUS_BUFFER_OVERFLOW is used when some, but not all, available data has been copied.

Buffer overflow errors in Regmon traces are relatively common. The documentation for RegQueryValueKey says:

If the buffer specified by lpData parameter is not large enough to hold the data, the function returns ERROR_MORE_DATA and stores the required buffer size in the variable pointed to by lpcbData. In this case, the contents of the lpData buffer are undefined.

If lpData is NULL, and lpcbData is non-NULL, the function returns ERROR_SUCCESS and stores the size of the data, in bytes, in the variable pointed to by lpcbData. This enables an application to determine the best way to allocate a buffer for the value's data.


There are two programming approaches commonly taken to reading variable-length Registry data. The first is to simply pass in a NULL pointer on the first call and if the call succeeds to allocate a buffer for a second query. The other approach is for an application to first try and use a static buffer of a size that the programmer expects will usually be large enough to receive the stored data. If the system reports ERROR_MORE_DATA, which is the Windows API equivalent of the native STATUS_BUFFER_OVERFLOW error, the application dynamically allocates a buffer of the required size and re-executes the query. The second approach has the advantage of avoiding a second query in most cases.

Given these approaches you should never see two buffer overflow errors in a row that query the same data. At least that’s what you’d expect, but on many occasions I’ve seen two buffer overflow errors followed by a third query of the same data that succeeds. Here’s an example I see on a Windows XP SP2 system that results when I open My Computer:



I decided to investigate this particular case as I was writing this blog posting. First, I started SoftICE and set a breakpoint on NtQueryValueKey. When the breakpoint triggered I single-stepped in SoftICE to the return instruction, at which point the status of the query is stored in the EAX register. I then cleared the first breakpoint, and set a conditional breakpoint on the return instruction for the case that the result is STATUS_BUFFER_OVERFLOW (0x800000005):

bpx _NtQueryValueKey+0346 IF eax==80000005

Then I opened My Computer and this is the stack at first buffer overflow breakpoint:



A look at the parameters Shlwapi passes into RegQueryValueExA revealed a NULL buffer pointer. I stepped back out into Shlwapi’s code and saw that if RegQueryValueExA returns ERROR_SUCCESS, which is the error code to which RegQueryValueExA translates STATUS_BUFFER_OVERFLOW if the caller uses a NULL buffer pointer, Shlwapi dynamically allocates a buffer of the required size and makes the call again:



Shlwapi makes one call into RegQueryValueExA, but two entries get added to Regmon's trace, one with a buffer overflow and one that's successful. Stepping into Advapi32’s implementation of RegQueryValueExA showed me why the second call results in two Registry queries in the Regmon trace. NtQueryValueKey returns a data structure storing several different pieces of information regarding the Registry value, including its type, length and title index:

typedef struct _KEY_VALUE_PARTIAL_INFORMATION {
ULONG TitleIndex;
ULONG Type;
ULONG DataLength;
UCHAR Data[1]; // Variable size
} KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;

However, RegQueryValueExA returns only the actual data into the caller's output buffer. RegQueryValueExA (and RegQueryValueExW) therefore uses a 144-byte stack-allocated buffer to query the value. This is the place in Advapi32 where RegQueryValueExA makes that call:



The first instruction in the disassembly is RegQueryValueExA loading the address of NtQueryValueKey into the ESI register. 144 is represented as 0x90 in hexadecimal, which you can see loaded into the EDI register and then passed as the fifth parameter to NtQueryValueKey, which corresponds to the output buffer size.

The additional value information included in the KEY_VALUE_PARTIAL_INFORMATION structure requires 12 bytes, so if the data being read is larger than 132 bytes NtQueryValueKey returns STATUS_BUFFER_OVERFLOW. If the caller’s buffer is large enough to store the data RegQueryValueExA allocates a buffer large enough to hold it and then executes the call to NtQueryValueKey again. After getting the data RegQueryValueExA copies it to the caller’s buffer.

When I saw the double-buffer overflows in the Regmon trace I thought it was evidence of poorly-written code, but my investigation showed that the pattern will be present in an application that reads Registry values larger than 132 bytes in size. What I don’t know is why the Windows API developers picked 132-bytes as the magical buffer size they expected would hold most Registry data.

On an unrelated node, I’m going to be in Orlando this week speaking at TechEd and delivering a Windows internals seminar with Dave Solomon. If you are attending either please let me know you read the blog. If you can’t make TechEd you can still catch my Understanding and Fighting Malware: Viruses, Spyware and Rootkits presentation the afternoon of Tuesday, June 7, via live web cast. Sign up here: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032274949&Culture=en-US  

android anr traces日志分析方法

一:什么是ANR ANR:Application Not Responding,即应用无响应 二:ANR的类型 ANR一般有三种类型: 1:KeyDispatchTimeout(5 secon...
  • qwiwuqo
  • qwiwuqo
  • 2014年10月15日 15:33
  • 34439

ORA-01455报错的问题探究

昨天同事说有个应用执行某个特殊操作时会报:ORA-01455: converting column overflows integer datatype 网上包括MOS上对1455报错介绍更...
  • bisal
  • bisal
  • 2014年04月01日 13:04
  • 7732

Android进阶-- /data/anr/traces.txt 文件丢失,ANR日志哪里去了 ?

为什么会写这篇文章? 那得从那个寒夜森森的夜晚说起了,正当俺们愉快玩耍的时候,测试同事在群里发了一条大家都不愿在这个节骨眼看到的消息~"XXX应用无响应。要将她关闭吗?"; 心中无数个T的...
  • janronehoo
  • janronehoo
  • 2017年03月15日 17:42
  • 4978

可软件定义的存储逻辑二——Energy适应性的分布式存储系统

提出了一个灵活的、可扩展的分布式存储系统,给它取名字flexStore。这个分布式存储系统可以非常好的适应数据中心中不停变化的能源,给去重的虚拟机磁盘IO存取带来很好的性能。这些研究人员研究并提出了一...
  • yin_wuzhe
  • yin_wuzhe
  • 2014年11月21日 11:19
  • 1260

Android traces.txt只保留最后一次发生ANR时的traces信息,那么以前的traces信息就丢失了么?

网络上关于ANR的种种神秘已经被大家解析得差不多了,这里我就来说说容易被大家忽略的地方,那就是Android traces.txt文件只保留最后一次发生ANR时的traces信息,那么以前的trace...
  • solidajun
  • solidajun
  • 2016年01月27日 15:34
  • 3567

强化学习各种算法分析及Eligibility Trace教程

Monte Carlo算法需要运行完整的episode,利用所有观察到的真是的reward(奖励值)来更新算法。Temporal Difference(TD)算法仅当前时刻采样的reward(奖励值)...
  • weixin_37895339
  • weixin_37895339
  • 2017年07月07日 11:45
  • 669

微处理器之Trace Cache浅析

问题背景是这样的:随着处理器内流水线越来越长,主频越来越高,分支问题带来的性能损失就越来越明显了。根据统计,分支指令占指令总数的10%(静态),15%(动态)。也就是说平均每处理6~7条指令就出现一条...
  • Hipercomer
  • Hipercomer
  • 2014年08月05日 21:09
  • 977

Buffer常用操作及原理分析

一个Buffer是一个固定数量的数据容器。其作用是一个存储器,或者分段运输区,在这里数据可被存储并在之后用于检索,对于每个非boolean原始数据类型都有一个缓冲区。尽管缓冲区作用于他们存储的原始数据...
  • YONGHUMING6342
  • YONGHUMING6342
  • 2016年08月19日 16:42
  • 344

Node.Js Buffer类(缓冲区)-(二)

一、合并缓冲区 Buffer.concat(list[, totalLength]) 参数描述如下: list - 用于合并的 Buffer 对象数组列表。 totalLength -...
  • u011127019
  • u011127019
  • 2016年09月12日 12:09
  • 1151

内存,cache,buffer

内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大。内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU...
  • hellojoy
  • hellojoy
  • 2015年08月19日 16:36
  • 758
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Buffer Overflows in Regmon Traces
举报原因:
原因补充:

(最多只允许输入30个字)