<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Caloni.com.br</title>
	<link>http://www.caloni.com.br/blog</link>
	<description>C++, Windows, Programação, Depuração e Transpiração</description>
	<pubDate>Tue, 31 Aug 2010 01:17:08 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2</generator>
	<language>en</language>
			<item>
		<title>Como ofuscar strings</title>
		<link>http://www.caloni.com.br/blog/archives/como-ofuscar-strings</link>
		<comments>http://www.caloni.com.br/blog/archives/como-ofuscar-strings#comments</comments>
		<pubDate>Mon, 30 Aug 2010 01:49:27 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Programação]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/como-ofuscar-strings</guid>
		<description><![CDATA[Já fiz ofuscamento e embaralhamento de dados acho que umas três ou quatro vezes. Dessa vez, parti para o batidíssimo esquema de fazer o pré-processamento de um header com defines que irão virar estruturas reaproveitadas por uma função padrão que desofusca e ofusca aquela tripa de bytes em algo legível: a string original.
Vamos ver um [...]]]></description>
			<content:encoded><![CDATA[<p>Já fiz ofuscamento e embaralhamento de dados acho que umas três ou quatro vezes. Dessa vez, parti para o batidíssimo esquema de fazer o pré-processamento de um header com defines que irão virar estruturas reaproveitadas por uma função padrão que desofusca e ofusca aquela tripa de bytes em algo legível: a string original.</p>
<p>Vamos ver um exemplo:</p>
<pre>#define MY_STR "Essa é minha string do coração"</pre>
<p>Conseguimos capturar os três elementos desse define (um descartável) por um simples scanf:</p>
<pre>scanf("#define %s \"%[^\"]", def, str);</pre>
<p>A função scanf retorna o número de argumentos capturados. Então se a coisa funcionou é só comparar com 2.</p>
<p>Depois de capturado, imprimimos na saída (o arquivo pós-processado) uma estrutura que irá conter nosso amigo embaralhado:</p>
<pre>printf("struct ST_%s { byte key; size_t bufferSize; byte buffer[%d] }\n"
	" %s = { %d, %d, { ";

for( ; ; ) printf(Cada byte ofuscado);

printtf(" } };\n");</pre>
<p>Pronto. Agora o usuário da string precisa abri-la usando uma macro esperta que irá chamar uma função esperta para desofuscar a string e entregar o ponteiro de buffer devidamente "casteado":</p>
<pre>#include "header-pos-processado.h"

#define ABRE_VAR(var, type) (type) OpenVar( (GENERIC_STRUCT) var)

int main()
{
	char* str = ABRE_VAR(MY_STR, char*);
}</pre>
<p>Uma vez que a abertura se faz "inplace", ou seja, a memória da própria variável da estrutura original é alterada, pode-se fechar a variável novamente, se quiser, após o uso.</p>
<pre>FECHA_VAR(MY_STR);</pre>
<p>A GENERIC_STRUCT do exemplo se trata apenas de um esqueleto para que todas as estruturas das 500 strings ofuscadas sejam entendidas a partir de um modelo. Sim, essa é uma solução usando linguagem C apenas, então não posso me dar ao luxo daqueles templates frescurentos.</p>
<pre>struct GENERIC_STRUCT
{
	byte key;
	size_t bufferSize;
	byte buffer[1];
};</pre>
<p>Como a string é ofuscada? Sei lá, use um XOR:</p>
<pre>for( size_t i = 0; i &lt; bufferSize; ++i )
	buffer[i] ^= key;</pre>
<p>Dessa forma abrir ou fechar a variável pode ser feito usando a mesma função.</p>
<p>Alguém aí gostaria de uma explicação didática sobre o operador XOR?</p>
<blockquote><p><em>PS: Acho que, além das minhas palestras, meus artigos estão também parecendo um brainstorm. </em></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/como-ofuscar-strings/feed</wfw:commentRss>
		</item>
		<item>
		<title>Gerando dumps automatizados</title>
		<link>http://www.caloni.com.br/blog/archives/gerando-dumps-automatizados</link>
		<comments>http://www.caloni.com.br/blog/archives/gerando-dumps-automatizados#comments</comments>
		<pubDate>Thu, 26 Aug 2010 11:53:00 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Depuração]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/gerando-dumps-automatizados</guid>
		<description><![CDATA[

Agora que a temporada das telas azuis passou estou às voltas com o nosso sistema de detecção de crashes, além de alguns dumps e logs pra relaxar de vez em quando.
Fiquei impressionado com a simplicidade com que podemos capturar qualquer exceção que ocorra em um programa, independente da thread, e gravar um minidump com o [...]]]></description>
			<content:encoded><![CDATA[

<p>Agora que a temporada das telas azuis passou estou às voltas com o nosso sistema de detecção de crashes, além de alguns dumps e logs pra relaxar de vez em quando.</p>
<p>Fiquei impressionado com a simplicidade com que podemos capturar qualquer exceção que ocorra em um programa, independente da thread, e gravar um minidump com o contexto exato em que o problema ocorreu. O uso da função API <a href="http://msdn.microsoft.com/en-us/library/ms680634%28VS.85%29.aspx">SetUnhandledExceptionFilter</a> aliado com a já citada na palestra <a href="http://msdn.microsoft.com/en-us/library/ms680360%28VS.85%29.aspx">MiniDumpWriteDump</a> pode agilizar muito a correção de crashes triviais como Access Violation.</p>
<p>A mágica é tão bela que resolvi gravar um vídeo do que ocorreu quando compilei e testei o programa abaixo. Note que o tamanho do arquivo de dump ficou em torno dos 10 KB, ridículos nessa era de barateamento de espaço.</p>
<p><pre><span style="color: #006600;">/** @file OnCrash
&nbsp;
@brief Exemplo de como capturar exce&ccedil;&otilde;es no seu programa.
&nbsp;
@author Wanderley Caloni &lt;wanderley@caloni.com.br&gt;
@date 2010-08
*/</span>
<span style="color: #006600;">#include &lt;windows.h&gt;</span>
<span style="color: #006600;">#include &lt;dbghelp.h&gt;</span>
<span style="color: #006600;">#include &lt;time.h&gt;</span>
&nbsp;
<span style="color: #006600;">#pragma comment(lib, &quot;dbghelp.lib&quot;)</span>
&nbsp;
&nbsp;
<span style="color: #0000ff;">LONG</span> WINAPI CrashHandler<span style="color: #000000; font-weight: bold;">&#40;</span>_EXCEPTION_POINTERS* ExceptionInfo<span style="color: #000000; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">&#123;</span>
	<span style="color: #0000ff;">LONG</span> ret = EXCEPTION_CONTINUE_SEARCH;
	MINIDUMP_EXCEPTION_INFORMATION minidumpInfo;
&nbsp;
	minidumpInfo.<span style="color: #000000;">ClientPointers</span> = <span style="color: #0000ff;">FALSE</span>;
	minidumpInfo.<span style="color: #000000;">ThreadId</span> = GetCurrentThreadId<span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">&#41;</span>;
	minidumpInfo.<span style="color: #000000;">ExceptionPointers</span> = ExceptionInfo;
&nbsp;
	HANDLE hFile = CreateFile<span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #666666;">"OnCrash.dmp"</span>, GENERIC_WRITE, <span style="color: #000000;">0</span>, <span style="color: #0000ff;">NULL</span>, CREATE_ALWAYS, <span style="color: #000000;">0</span>, <span style="color: #0000ff;">NULL</span><span style="color: #000000; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #0000ff;">if</span><span style="color: #000000; font-weight: bold;">&#40;</span> hFile != INVALID_HANDLE_VALUE <span style="color: #000000; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">&#123;</span>
		MINIDUMP_TYPE dumpType = MiniDumpNormal;
&nbsp;
		<span style="color: #0000ff;">if</span><span style="color: #000000; font-weight: bold;">&#40;</span> MiniDumpWriteDump<span style="color: #000000; font-weight: bold;">&#40;</span>GetCurrentProcess<span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">&#41;</span>, GetCurrentProcessId<span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">&#41;</span>, 
			hFile, MiniDumpNormal, &amp;minidumpInfo, <span style="color: #0000ff;">NULL</span>, <span style="color: #0000ff;">NULL</span><span style="color: #000000; font-weight: bold;">&#41;</span> <span style="color: #000000; font-weight: bold;">&#41;</span>
		<span style="color: #000000; font-weight: bold;">&#123;</span>
			ret = EXCEPTION_EXECUTE_HANDLER;
		<span style="color: #000000; font-weight: bold;">&#125;</span>
&nbsp;
		CloseHandle<span style="color: #000000; font-weight: bold;">&#40;</span>hFile<span style="color: #000000; font-weight: bold;">&#41;</span>;
	<span style="color: #000000; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #0000ff;">return</span> ret;
<span style="color: #000000; font-weight: bold;">&#125;</span>
&nbsp;
&nbsp;
DWORD WINAPI CrashThread<span style="color: #000000; font-weight: bold;">&#40;</span>PVOID<span style="color: #000000; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">&#123;</span>
	<span style="color: #0000ff;">int</span>* x = <span style="color: #000000;">0</span>;
	*x = <span style="color: #000000;">13</span>;
	<span style="color: #0000ff;">return</span> <span style="color: #000000;">0</span>;
<span style="color: #000000; font-weight: bold;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">&#123;</span>
	SetUnhandledExceptionFilter<span style="color: #000000; font-weight: bold;">&#40;</span>CrashHandler<span style="color: #000000; font-weight: bold;">&#41;</span>;
	HANDLE crashThread = CreateThread<span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #0000ff;">NULL</span>, <span style="color: #000000;">0</span>, CrashThread, <span style="color: #0000ff;">NULL</span>, <span style="color: #000000;">0</span>, <span style="color: #0000ff;">NULL</span><span style="color: #000000; font-weight: bold;">&#41;</span>;
	WaitForSingleObject<span style="color: #000000; font-weight: bold;">&#40;</span>crashThread, INFINITE<span style="color: #000000; font-weight: bold;">&#41;</span>;
<span style="color: #000000; font-weight: bold;">&#125;</span></pre></p>
<p><a href="http://www.caloni.com.br/blog/wp-content/uploads/finddump.htm" title="oncrash.png"></a></p>
<p style="text-align: center"><a href="http://www.caloni.com.br/blog/wp-content/uploads/finddump.htm" title="oncrash.png"><img src="http://www.caloni.com.br/blog/wp-content/uploads/oncrash.png" alt="oncrash.png" height="415" width="568" /></a></p>
<p>Espero com isso aliviar a carga pesada de A.V.s que sempre aparece quando menos se espera. Cuidar de toneladas de código legado exige algumas pitadas de automatização nos lugares certos. Como já dizia meu primeiro chefe: se a mente não pensa...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/gerando-dumps-automatizados/feed</wfw:commentRss>
		</item>
		<item>
		<title>Evento C++</title>
		<link>http://www.caloni.com.br/blog/archives/evento-c</link>
		<comments>http://www.caloni.com.br/blog/archives/evento-c#comments</comments>
		<pubDate>Mon, 16 Aug 2010 16:36:58 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Depuração]]></category>

		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/evento-c</guid>
		<description><![CDATA[Esse fim-de-semana houve o tão falado evento C++, com a presença de dezenas de pessoas, algo que eu sinceramente não esperava. O bom desse evento foi saber que existem tantas pessoas interessadas em manter contato com quem gosta e pratica essa linguagem e também em saber que o nível técnico das palestras estão de alto [...]]]></description>
			<content:encoded><![CDATA[<p>Esse fim-de-semana houve o tão falado evento C++, com a presença de dezenas de pessoas, algo que eu sinceramente não esperava. O bom desse evento foi saber que existem tantas pessoas interessadas em manter contato com quem gosta e pratica essa linguagem e também em saber que o nível técnico das palestras estão de alto para avançado.</p>
<p>Infelizmente em nenhuma das duas palestras práticas (minha e do Fernando) houve participação interativa, e ninguém que eu saiba abriu meu pacote-surpresa com os dumps a serem analisados. De qualquer forma, minha palestra ficou bagunçada pelo excesso de conteúdo e falta de tempo, o que me fez dar boas risadas ao ouvir no twitter que <a href="http://twitter.com/nicolasgavlak/status/21201995301" title="Twitter">minha palestra foi mais um brainstorm</a>. A intenção não era essa, claro, mas meu claro despreparo para muito conteúdo gerou essa impressão. Espero que do pouco que consegui explicar alguém tenha achado utilidade.</p>
<p>E, pelo jeito, futuramente irei aplicar essa mesma metodologia brainstorm em um videocast, que ainda não decidi como irei preparar. A ideia é analisarmos alguns dumps em conjunto e, para os que acompanharem online, a interatividade de perguntas &amp; respostas.</p>
<p>Mas enquanto isso não acontece vamos dar uma olhada no que tínhamos no <a href="http://www.caloni.com.br/blog/archives/nao-e-minha-culpa">pacote-surpresa</a>.</p>
<h4>1. NotMyFaultEither.exe.mdmp - Stack Trash</h4>
<pre>0:000&gt; kv
ChildEBP RetAddr  Args to Child
0012b200 7c90df3c 7c8025db 000000e8 00000000 ntdll!KiFastSystemCallRet
0012b204 7c8025db 000000e8 00000000 0012b238 ntdll!NtWaitForSingleObject+0xc
0012b268 7c802542 000000e8 000493e0 00000000 kernel32!WaitForSingleObjectEx+0xa8
0012b27c 6998ada6 000000e8 000493e0 003a0043 kernel32!WaitForSingleObject+0x12
0012bd70 6998aff1 000000c4 00000568 000000d0 faultrep!InternalGenerateMinidumpEx+0x335
0012bd9c 6998b50a 000000c4 00000568 0012c698 faultrep!InternalGenerateMinidump+0x75
0012c678 69986652 000000c4 00000568 0012c698 faultrep!InternalGenFullAndTriageMinidumps+0x8a
0012dea0 69987d3d 0012df18 0015c300 00000000 faultrep!ReportFaultDWM+0x4e5
0012e398 699882d8 0040a1dc 0012f1e0 ffffffff faultrep!StartManifestReportImmediate+0x268
0012f404 7c8643c6 0040a1dc ffffffff 0012fc24 faultrep!ReportFault+0x55a
Unable to load image C:\Documents and Settings\Administrador\Desktop\NotMyFaultEither.exe
*** WARNING: Unable to verify timestamp for NotMyFaultEither.exe
*** ERROR: Module load completed but symbols could not be loaded for NotMyFaultEither.exe
0012f678 004018aa 0040a1dc e280eec4 1d7f113b kernel32!UnhandledExceptionFilter+0x55b
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f9ac 00401357 <font color="#ff0000">dededede dededede dededede</font> NotMyFaultEither+0x18aa
0012fbe8 <font color="#ff0000">dededede dededede dededede dededede</font> NotMyFaultEither+0x1357
0012fbec <font color="#ff0000">dededede dededede dededede dededede</font> 0xdededede
0012fbf4 <font color="#ff0000">dededede dededede dededede dededede</font> 0xdededede
...</pre>
<p>Como foi visto na palestra, uma pilha nesse estado demonstra claramente alguma variável que estourou e corrompeu o resto da pilha de chamadas. Na hora de voltar para a função chamadora, o endereço usado foi o endereço reescrito por lixo, e daí temos o "crash-pattern" Stack Trash.</p>
<h4>2. NotMyFaultEither.mdmp - Dead Lock</h4>
<pre>0:000&gt; kv
ChildEBP RetAddr  Args to Child
0012f900 7c90df3c 7c8025db 0000007c 00000000 ntdll!KiFastSystemCallRet
0012f904 7c8025db <font color="#ff0000">0000007c </font>00000000 00000000 ntdll!NtWaitForSingleObject+0xc
0012f968 7c802542 0000007c ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8
0012f97c 00401176 0000007c ffffffff 00000111 kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f9c0 7c910202 00000002 001506e8 00150000 NotMyFaultEither+0x1176
0012f9f8 7e3746d3 01010050 00000000 00000000 ntdll!RtlpAllocateFromHeapLookaside+0x42
0012fa5c 7e382672 01010050 01100068 7e3a4716 user32!DrawStateW+0x5cd
0012fae8 7e382c75 001563ac 01010050 00000003 user32!xxxBNDrawText+0x313
0012fb20 002d0036 00000000 00000020 0012fb3c user32!xxxDrawButton+0xbb
0012fb30 7e3799d8 0000800a 0012fbc8 7e375ba2 0x2d0036
0012fb3c 7e375ba2 0000800a 002d0036 fffffffc user32!NotifyWinEvent+0xd
0012fbc8 00000000 002d0036 004011b0 dcbaabcd user32!ButtonWndProcWorker+0x79b
0:000&gt; !handle 0000007c
Handle <font color="#ff0000">0000007c</font>
  Type         	<font color="#ff0000">Thread</font>
0:000&gt; ~* kv

.  0  Id: 5e4.<font color="#008000">39c </font>Suspend: 0 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr  Args to Child
0012f900 7c90df3c 7c8025db 0000007c 00000000 ntdll!KiFastSystemCallRet
0012f904 7c8025db 0000007c 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
0012f968 7c802542 0000007c ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8
0012f97c 00401176 0000007c ffffffff 00000111 kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f9c0 7c910202 00000002 001506e8 00150000 NotMyFaultEither+0x1176
0012f9f8 7e3746d3 01010050 00000000 00000000 ntdll!RtlpAllocateFromHeapLookaside+0x42
0012fa5c 7e382672 01010050 01100068 7e3a4716 user32!DrawStateW+0x5cd
0012fae8 7e382c75 001563ac 01010050 00000003 user32!xxxBNDrawText+0x313
0012fb20 002d0036 00000000 00000020 0012fb3c user32!xxxDrawButton+0xbb
0012fb30 7e3799d8 0000800a 0012fbc8 7e375ba2 0x2d0036
0012fb3c 7e375ba2 0000800a 002d0036 fffffffc user32!NotifyWinEvent+0xd
0012fbc8 00000000 002d0036 004011b0 dcbaabcd user32!ButtonWndProcWorker+0x79b

   1  Id: 5e4.6a4 Suspend: 0 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr  Args to Child
00b8ff10 7c90df3c 7c91b22b 00000080 00000000 ntdll!KiFastSystemCallRet
00b8ff14 7c91b22b 00000080 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
00b8ff9c 7c901046 0040e940 004010e0 0040e940 ntdll!RtlpWaitForCriticalSection+0x132
00b8ffa4 004010e0 <font color="#0000ff">0040e940 </font>00000000 00000000 ntdll!RtlEnterCriticalSection+0x46
WARNING: Stack unwind information not available. Following frames may be wrong.
00b8ffec 00000000 004010c0 0012f99c 00000000 NotMyFaultEither+0x10e0
0:000&gt; !cs <font color="#0000ff">0040e940</font>
-----------------------------------------
Critical section   = 0x0040e940 (NotMyFaultEither+0xE940)
DebugInfo          = 0x00154498
<font color="#0000ff">LOCKED</font>
LockCount          = 0x1
OwningThread       = <font color="#008000">0x0000039c</font>
RecursionCount     = 0x1
LockSemaphore      = 0x80
SpinCount          = 0x00000000</pre>
<p>A thread ativa no momento do dump aguardava por outra thread. Listando todas as threads do processo temos a primeira e a segunda, que tenta entrar em um critical section. Quando vemos que aquele CS estava sendo bloqueado pela primeira thread vemos claramente se tratar de um dead lock.</p>
<h4>3. NotMyFaultEither_100808_172407.dmp - Access Violation</h4>
<pre>0:000&gt; kv
ChildEBP RetAddr  Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f9cc 7e37f916 01010052 005a0049 0012f9f4 NotMyFaultEither+0x10a3
0012fa58 7e37f991 01010052 00000043 01100076 user32!ClientFrame+0xe0
0012fa7c 7e382909 01010052 0012fa98 00000000 user32!DrawFocusRect+0x40
0012fae8 7e382c75 00156304 01010052 00000003 user32!xxxBNDrawText+0x3e9
0012fb20 001100a0 00000000 00000020 0012fb3c user32!xxxDrawButton+0xbb
0012fb30 7e3799d8 0000800a 0012fbc8 7e375ba2 0x1100a0
0012fb3c 7e375ba2 0000800a 001100a0 fffffffc user32!NotifyWinEvent+0xd
0012fbc8 00000000 001100a0 004010f0 dcbaabcd user32!ButtonWndProcWorker+0x79b
0:000&gt; <font color="#ff0000">? eax+edx</font>
Evaluate expression: 0 = <font color="#ff0000">00000000</font>
0:000&gt; u
NotMyFaultEither+0x10a3:
004010a3 66890c02        mov     word ptr [<font color="#ff0000">edx+eax</font>],cx
004010a7 83c002          add     eax,2
004010aa 6685c9          test    cx,cx</pre>
<p>O disassemble da instrução inválida tenta escrever claramente em cima do endereço zerado (edx + eax). Dessa forma fica fácil saber que esse tipo de escrita não é permitido, constituindo nosso famosíssimo AV.</p>
<h4>4. NotMyFaultEither_100808_175404.dmp - Exception not Handled</h4>
<pre>eax=00000000 ebx=00000111 ecx=7c91003d edx=00010000 esi=00330120 edi=7e374dfa
eip=7c90120e esp=0012f9a0 ebp=00000001 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
<font color="#ff0000">7c90120e cc              int     3</font>
0:000&gt; kv
ChildEBP RetAddr  Args to Child
0012f99c 004011ec 0012fc24 004010d0 0012fbe8 <font color="#ff0000">ntdll!DbgBreakPoint</font> (FPO: [0,0,0])
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f9cc 7e37f916 01010054 005a0049 0012f9f4 NotMyFaultEither+0x11ec
0012fa58 7e37f991 01010054 00000043 01100076 user32!ClientFrame+0xe0</pre>
<p>Esse foi meio de brinde. Uma exceção de breakpoint (int 3, ntdll!DbgBreakPoint) lançada sem um depurador atachado implica em derrubamento do processo, pois é uma exceção como outra qualquer. O programador deve ter esquecido um DebugBreak ou algo que o valha no código de produção, que acabou sendo executado.</p>
<h5>5. ntdll_cliente.dll - Importação de símbolos</h5>
<p><a href="http://www.caloni.com.br/blog/wp-content/uploads/vm-sony-xp-2010-08-08-17-59-22.png" title="vm-sony-xp-2010-08-08-17-59-22.png"><img src="http://www.caloni.com.br/blog/wp-content/uploads/vm-sony-xp-2010-08-08-17-59-22.png" alt="vm-sony-xp-2010-08-08-17-59-22.png" /></a><br />
Essa foi a DLL encontrada no cliente quando ocorreu o problema relatado na imagem, também em anexo. Isso foi demonstrado na palestra com a ajuda do meu script que carrega DLLs, além de um pouco de sorte. Podemos analisar esse caso com mais calma em outro artigo. Acho que já falei demais por aqui.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/evento-c/feed</wfw:commentRss>
		</item>
		<item>
		<title>Foto dos melhores momentos</title>
		<link>http://www.caloni.com.br/blog/archives/foto-dos-melhores-momentos</link>
		<comments>http://www.caloni.com.br/blog/archives/foto-dos-melhores-momentos#comments</comments>
		<pubDate>Thu, 12 Aug 2010 02:37:12 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Depuração]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/foto-dos-melhores-momentos</guid>
		<description><![CDATA[ Mais um quebra-cabeças antes da nossa palestra, esse "baseado em fatos reais".
A história é a seguinte: o cliente instalou uma versão nova do produto em algumas máquinas que, ato contínuo, começaram a apresentar telas azuis constantemente. Como essas máquinas tinham que ser usadas pelos funcionários, a administradora rapidamente desinstalou essa versão buguenta, e logo [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.caloni.com.br/blog/wp-content/uploads/telaazul_0309.jpg" title="Tela azul de recordação"><img src="http://www.caloni.com.br/blog/wp-content/uploads/telaazul_0309.thumbnail.jpg" alt="Tela azul de recordação" /></a> Mais um quebra-cabeças antes da nossa palestra, esse "baseado em fatos reais".</p>
<p>A história é a seguinte: o cliente instalou uma versão nova do produto em algumas máquinas que, ato contínuo, começaram a apresentar telas azuis constantemente. Como essas máquinas tinham que ser usadas pelos funcionários, a administradora rapidamente desinstalou essa versão buguenta, e logo em seguida pediu por uma correção.</p>
<p>Até aí tudo bem. O problema maior era que ninguém havia capturado dump de nada.</p>
<p>Por isso pedi encarecidamente por qualquer fragmento de tela azul (minidumps) que pudessem ainda estar nas máquinas afetadas. Dito isso, ela confessou que havia voltado a imagem padrão nesses equipamentos para que os funcionários pudessem voltar ao trabalho rapidamente. Só que sem dump eu não conseguiria trabalhar rapidamente.</p>
<p>Mas eis que no dia seguinte ela me liga, comentando que um funcionário, empolgado (?) pela tela azul em sua máquina, havia tirado uma foto da mesma para "recordação". Sem nenhuma cerimônia, então, pedi rapidamente que ela conseguisse essa foto para a minha coleção. A foto que ela me manda é exatamente a que está no início desse artigo (clique na foto para ampliá-la), apenas censurado o nome do driver, o que não vem ao caso. Assim que a recebi pude constatar o problema direto no código-fonte, corrigi-lo e enviar uma nova versão, que após alguns dias de testes se revelou bem sucedida.</p>
<p>A questão é: como eu resolvi o problema? Como você teria procedido nessa situação?</p>
<p>A resposta para esse enigma também contará pontos para nossa brincadeira com o livro Windows Internals, como foi explicado no artigo anterior. Vamos lá, Sherlock!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/foto-dos-melhores-momentos/feed</wfw:commentRss>
		</item>
		<item>
		<title>Não é minha culpa</title>
		<link>http://www.caloni.com.br/blog/archives/nao-e-minha-culpa</link>
		<comments>http://www.caloni.com.br/blog/archives/nao-e-minha-culpa#comments</comments>
		<pubDate>Sun, 08 Aug 2010 22:23:16 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Depuração]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/nao-e-minha-culpa</guid>
		<description><![CDATA[Recebi a dica de meu amigo kernel-mode sobre o aplicativo NotMyFault, escrito como ferramenta do livro Windows Internals e que basicamente gera telas azuis para análise.
Como os problemas gerados pela ferramenta são todos de kernel, resolvi escrever meu próprio conjunto de bugs para o pessoal da userland. E como nada na vida se cria, tudo [...]]]></description>
			<content:encoded><![CDATA[<p>Recebi a dica de meu <a href="http://www.driverentry.com.br">amigo kernel-mode</a> sobre o aplicativo <a href="http://download.sysinternals.com/Files/Notmyfault.zip">NotMyFault</a>, escrito como ferramenta do livro <a href="http://technet.microsoft.com/en-us/sysinternals/bb963901.aspx">Windows Internals</a> e que basicamente gera telas azuis para análise.</p>
<p>Como os problemas gerados pela ferramenta são todos de kernel, resolvi escrever meu próprio conjunto de bugs para o pessoal da userland. E como nada na vida se cria, tudo se copia, tenho o orgulho de apresentar a vocês o <strong>NotMyFaultEither</strong>!</p>
<p><img src="http://www.caloni.com.br/blog/wp-content/uploads/notmyfaulteither.png" alt="notmyfaulteither.png" /> <img src="http://www.caloni.com.br/blog/wp-content/uploads/notmyfaulteither-crash.png" alt="notmyfaulteither-crash.png" /></p>
<p>Seu uso é bem simples. Escolha o problema, aperte a teclar "Fazer Bug" e pronto!</p>
<p>O resultado pode variar dependendo do sistema operacional e da arquitetura (há versões 32 e 64 bits, ambas UNICODE). Um Access Violation no Windows Seven 64 bits, por exemplo, o processo pára de reponder.</p>
<p>Após a análise do SO ele exibe uma tela onde é possível achar onde está o despejo de memória que podemos usar.</p>
<p><img src="http://www.caloni.com.br/blog/wp-content/uploads/notmyfaulteither-crash-dump-automatic.png" alt="notmyfaulteither-crash-dump-automatic.png" />   <img src="http://www.caloni.com.br/blog/wp-content/uploads/notmyfaulteither-crash-dump-task-manager.png" alt="notmyfaulteither-crash-dump-task-manager.png" /></p>
<p>Esse é um minidump (mdmp), que possui a pilha da thread faltosa e informações de ambiente. Podemos gerar um dump completo através do Gerenciador de Tarefas.</p>
<p>No caso do Windows XP, podemos executar processo semelhante para gerar o dump através do aplicativo <a href="http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx">ProcDump</a>, muito útil para preparar o material da <a href="http://www.temporealeventos.com.br/?area=95&amp;tipo=1&amp;id=3360">minha palestra do próximo fim de semana</a>.</p>
<h4>Sorteio do livro Windows Internals, Quarta Edição</h4>
<p><img src="http://www.caloni.com.br/blog/wp-content/uploads/meuwindowsinternals.jpg" title="meuwindowsinternals.jpg" alt="meuwindowsinternals.jpg" align="baseline" height="236" width="177" />E por falar em palestra, criei um <a href="http://www.caloni.com.br/blog/wp-content/uploads/crash-dump-analysis-dumps.7z" title="crash-dump-analysis-dumps.7z">pacote-surpresa</a> de alguns minidumps para análise. Se alguém tiver a curiosidade de já ir mexendo, ou de mexer na hora da apresentação, fique à vontade. Quem montar uma lista relacionando cada dump com o tipo de problema encontrado (não precisa estar completa) irá concorrer, no dia da palestra, à quarta edição do livro Windows Internals, de Mark Russinovich. É minha cópia pessoal, mas está bem novinho, visto que a original pesa pra caramba e consulto sempre o e-book.</p>
<p>Estarei usando estes mesmos minidumps na palestra, junto dos dumps completos. Mas é claro que eu não iria deixar um despejo de memória completo pra vocês. Iria tornar as coisas muito fáceis <img src='http://www.caloni.com.br/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Portanto, junte suas grandes dúvidas para o grande dia e nos vemos lá.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/nao-e-minha-culpa/feed</wfw:commentRss>
		</item>
		<item>
		<title>Novas diferenças no Bazaar</title>
		<link>http://www.caloni.com.br/blog/archives/novas-diferencas-no-bazaar</link>
		<comments>http://www.caloni.com.br/blog/archives/novas-diferencas-no-bazaar#comments</comments>
		<pubDate>Wed, 04 Aug 2010 12:47:13 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Controle de Fonte]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/novas-diferencas-no-bazaar</guid>
		<description><![CDATA[Novidade incrível nas novas versões do Bazaar. Dando continuidade à sua versão boiola gráfica, agora é possível configurar quantos visualizadores de diferenças você quiser. Na hora de ver a diferença em algum código-fonte, você pode optar pelo enrustido embutido ou, no caso, o meu favorito, WinMerge.

E por que o WinMerge é meu favorito? Porque você [...]]]></description>
			<content:encoded><![CDATA[<p>Novidade incrível nas novas versões do Bazaar. Dando continuidade à sua versão <strike>boiola</strike> gráfica, agora é possível configurar quantos visualizadores de diferenças você quiser. Na hora de ver a diferença em algum código-fonte, você pode optar pelo <strike>enrustido</strike> embutido ou, no caso, o meu favorito, WinMerge.</p>
<p><img src="http://www.caloni.com.br/blog/wp-content/uploads/bzr-qconfig-diff.png" alt="bzr-qconfig-diff.png" /></p>
<p>E por que o WinMerge é meu favorito? Porque você pode ignorar toda aquela discussão se devemos usar tabs ou três espaços para indentar o código. Cada um indenta como quer, na hora que mexer no código, que o WinMerge não vai nem ligar para essas diferencinhas (já que o compilador não liga). Ele até detecta blocos de código inteiros que foram movidos dentro do arquivo.</p>
<p><img src="http://www.caloni.com.br/blog/wp-content/uploads/winmerge-config.png" alt="winmerge-config.png" /></p>
<p>Na hora de ver as diferenças no worktree podemos usar a velha opção de criar um alias para o WinMerge. Mas no meio de um log, podemos ativar tanto o view embutido quanto o de qualquer outra ferramenta que escolhermos.</p>
<p><img src="http://www.caloni.com.br/blog/wp-content/uploads/bzr-qlog-view-diff.png" alt="bzr-qlog-view-diff.png" /></p>
<p>Vendo essas coisas fico imaginando como ainda tem gente que usa arquivos zip com data para armazenar versões de documentos diferentes. Tsc, tsc.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/novas-diferencas-no-bazaar/feed</wfw:commentRss>
		</item>
		<item>
		<title>Como achar o código-fonte sem símbolos</title>
		<link>http://www.caloni.com.br/blog/archives/como-achar-o-codigo-fonte-sem-simbolos</link>
		<comments>http://www.caloni.com.br/blog/archives/como-achar-o-codigo-fonte-sem-simbolos#comments</comments>
		<pubDate>Tue, 03 Aug 2010 11:30:13 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Engenharia Reversa]]></category>

		<category><![CDATA[Depuração]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/como-achar-o-codigo-fonte-sem-simbolos</guid>
		<description><![CDATA[





Continuo escovando bits. Dessa vez de forma mais nervosa. Se trata de um serviço que trava durante seu stop. Um colega muito esperto do suporte gerou um dump para mim, tornando as coisas mais fáceis. O problema era que não havia símbolos nem código-fonte que batessem exatamente com aquela compilação de 2004. Solução? Analisar as [...]]]></description>
			<content:encoded><![CDATA[





<p>Continuo escovando bits. Dessa vez de forma mais nervosa. Se trata de um serviço que trava durante seu stop. Um colega muito esperto do suporte gerou um dump para mim, tornando as coisas mais fáceis. O problema era que não havia símbolos nem código-fonte que batessem exatamente com aquela compilação de 2004. Solução? Analisar as pilhas das threads restantes.</p>
<p>É sabido que esse serviço responde requisições de milhares de máquinas em um período curto de tempo, então por isso a primeira coisa que me atentei foi verificar quantas threads haviam:</p>
<pre>0:000&gt; ~*
.  0  Id: 4c8.30c Suspend: 1 Teb: 7ffde000 Unfrozen
      Start: *** WARNING: Unable to verify checksum for Service.exe
*** ERROR: Module load completed but symbols could not be loaded for Service.exe
Service+0xc60c (0040c60c)
      Priority: 0  Priority class: 32  Affinity: f
   1  Id: 4c8.4d8 Suspend: 1 Teb: 7ffdd000 Unfrozen
      Start: ADVAPI32!AccessCheckByTypeResultListAndAudit(...)
      Priority: 0  Priority class: 32  Affinity: f
   2  Id: 4c8.580 Suspend: 1 Teb: 7ffdc000 Unfrozen
      Priority: 0  Priority class: 32  Affinity: f
   3  Id: 4c8.adc Suspend: 1 Teb: 7ffd9000 Unfrozen
      Start: rtutils!TraceServerThread (778321fe)
      Priority: 0  Priority class: 32  Affinity: f
   4  Id: 4c8.f1c Suspend: 1 Teb: 7ffa5000 Unfrozen
      Start: rpcrt4!ThreadStartRoutine (77d37e70)
      Priority: 0  Priority class: 32  Affinity: f
...
 1426  Id: 4c8.1464 Suspend: 1 Teb: 7fa0c000 Unfrozen
      Start: rpcrt4!ThreadStartRoutine (77d37e70)
      Priority: 0  Priority class: 32  Affinity: f
 1427  Id: 4c8.144c Suspend: 1 Teb: 7fa0b000 Unfrozen
      Start: rpcrt4!ThreadStartRoutine (77d37e70)
      Priority: 0  Priority class: 32  Affinity: f
 1428  Id: 4c8.12dc Suspend: 1 Teb: 7fa09000 Unfrozen
      Start: rpcrt4!ThreadStartRoutine (77d37e70)
      Priority: 0  Priority class: 32  Affinity: f
 1429  Id: 4c8.1410 Suspend: 1 Teb: 7fa08000 Unfrozen
      Start: rpcrt4!ThreadStartRoutine (77d37e70)
      Priority: 0  Priority class: 32  Affinity: f
 <font color="#ff0000">1430  </font>Id: 4c8.143c Suspend: 1 Teb: 7fa06000 Unfrozen
      Priority: 0  Priority class: 32  Affinity: f</pre>
<p>São muitas.</p>
<p>Analisar essa quantidade absurda de threads seria um saco. Além de inútil. Foi por isso deus inventou a função <strong>!uniqstack</strong>, que encontra automagicamente quais threads estão com a pilha duplicada.</p>
<pre>0:000&gt; !uniqstack
Processing 1431 threads, please wait

.  0  Id: 4c8.30c Suspend: 1 Teb: 7ffde000 Unfrozen
      Start: Service+0xc60c (0040c60c)
      Priority: 0  Priority class: 32  Affinity: f
ChildEBP RetAddr
0012f9f8 7c586381 NTDLL!ZwReadFile+0xb
0012fa6c 7c2dd578 KERNEL32!ReadFile+0x181
...
0012fff0 00000000 KERNEL32!BaseProcessStart+0x3d

.  1  Id: 4c8.4d8 Suspend: 1 Teb: 7ffdd000 Unfrozen
      Start: ADVAPI32!AccessCheckByTypeResultListAndAudit(...)
      Priority: 0  Priority class: 32  Affinity: f
ChildEBP RetAddr
00cefec0 7c59a0a2 NTDLL!ZwWaitForSingleObject+0xb
...
00cf000c 007a0000 0x1366e0
00cf000c 00000000 0x7a0000

.  2  Id: 4c8.580 Suspend: 1 Teb: 7ffdc000 Unfrozen
      Priority: 0  Priority class: 32  Affinity: f
ChildEBP RetAddr
010efe24 77d59815 NTDLL!ZwReplyWaitReceivePortEx+0xb
...
010effec 00000000 KERNEL32!BaseThreadStart+0x52

.  3  Id: 4c8.adc Suspend: 1 Teb: 7ffd9000 Unfrozen
      Start: rtutils!TraceServerThread (778321fe)
      Priority: 0  Priority class: 32  Affinity: f
ChildEBP RetAddr
0150fd20 7c59a26d NTDLL!ZwWaitForMultipleObjects+0xb
...
0150ffec 00000000 KERNEL32!BaseThreadStart+0x52
...
.1430  Id: 4c8.143c Suspend: 1 Teb: 7fa06000 Unfrozen
      Priority: 0  Priority class: 32  Affinity: f
ChildEBP RetAddr
6665f0dc 7c59a0a2 NTDLL!ZwWaitForSingleObject+0xb
...
6665ffec 00000000 KERNEL32!BaseThreadStart+0x52

Total threads: 1431
Duplicate callstacks: <font color="#ff0000">1092 </font>(windbg thread #s follow):
7, 9, 11, 12, 13, 14, 15, 17, 18, 20, 21, (...), 1428, 1429</pre>
<p>Muitas threads duplicadas. Isso quer dizer que podemos nos focar na pilha de uma delas. Basta pegar uma.</p>
<pre>0:000&gt; ~1429 kv

<font color="#ff0000"></font><font color="#008000">ChildEBP </font>RetAddr  Args to Child
6645f334 7c59a0a2 ... NTDLL!ZwWaitForSingleObject+0xb (FPO: [3,0,0])
6645f35c 7c57b40f ... KERNEL32!WaitForSingleObjectEx+0x71 (FPO: [Non-Fpo])
6645f36c 004054c3 ... KERNEL32!WaitForSingleObject+0xf (FPO: [2,0,0])
WARNING: Stack unwind information not available. Following frames may be wrong.
<font color="#000000">6645f690 004060ec ... Service+0x54c3
6645f764 </font><font color="#ff0000">77d79970 </font>... <font color="#ff0000">Service+0x60ec</font>
<font color="#008000">6645f788 </font>77d96460 ... rpcrt4!Invoke+0x30
6645f7a0 77d9637a ... rpcrt4!NdrCallServerManager+0x15 (FPO: [4,0,2])
6645fa90 77d9076f ... rpcrt4!NdrStubCall+0x200 (FPO: [Non-Fpo])
6645faf4 7cef55fd ... rpcrt4!CStdStubBuffer_Invoke+0xc1 (FPO: [Non-Fpo])
6645fb38 7cef58d8 ... OLE32!SyncStubInvoke+0x61 (FPO: [Non-Fpo])
6645fb80 7ce8833d ... OLE32!StubInvoke+0xa8 (FPO: [Non-Fpo])
6645fbe4 7ce7a711 ... OLE32!CCtxComChnl::ContextInvoke+0xbb (FPO: [Non-Fpo])
6645fc00 7cef54e2 ... OLE32!MTAInvoke+0x18 (FPO: [Non-Fpo])
6645fc30 7cef5c06 ... OLE32!AppInvoke+0xb5 (FPO: [Non-Fpo])
6645fcf0 7cef3360 ... OLE32!ComInvokeWithLockAndIPID+0x297 (FPO: [Non-Fpo])
6645fd30 77d545b1 ... OLE32!ThreadInvoke+0x1b7 (FPO: [Non-Fpo])
6645fd68 77d39463 ... rpcrt4!DispatchToStubInC+0x32 (FPO: [Non-Fpo])
6645fdc0 77d39337 ... rpcrt4!RPC_INTERFACE::DispatchToStubWorker+0x100 (FPO: [Non-Fpo])
6645fde0 77d39603 ... rpcrt4!RPC_INTERFACE::DispatchToStub+0x5e (FPO: [Non-Fpo])
6645fe10 77d4740d ... rpcrt4!RPC_INTERFACE::DispatchToStubWithObject+0xa9 (FPO: [Non-Fpo])
6645fe44 77d47634 ... rpcrt4!OSF_SCALL::DispatchHelper+0xa1 (FPO: [Non-Fpo])
6645fe58 77d46f3b ... rpcrt4!OSF_SCALL::DispatchRPCCall+0x121 (FPO: [Non-Fpo])
6645fe90 77d466ac ... rpcrt4!OSF_SCALL::ProcessReceivedPDU+0x68f (FPO: [Non-Fpo])
6645feb0 77d48730 ... rpcrt4!OSF_SCALL::BeginRpcCall+0x183 (FPO: [Uses EBP] [2,0,4])
6645ff10 77d5154b ... rpcrt4!OSF_SCONNECTION::ProcessReceiveComplete+0x326 (FPO: [Non-Fpo])
6645ff20 77d516b8 ... rpcrt4!ProcessConnectionServerReceivedEvent+0x1b (FPO: [7,0,0])
6645ff74 77d514bd ... rpcrt4!LOADABLE_TRANSPORT::ProcessIOEvents+0xcd (FPO: [Non-Fpo])
6645ff78 77d3af8d ... rpcrt4!ProcessIOEventsWrapper+0x9 (FPO: [1,0,0])
6645ffa8 77d37e88 ... rpcrt4!BaseCachedThreadRoutine+0x4f (FPO: [Non-Fpo])
6645ffb4 7c57b3bc ... rpcrt4!ThreadStartRoutine+0x18 (FPO: [Non-Fpo])
6645ffec 00000000 ... KERNEL32!BaseThreadStart+0x52 (FPO: [Non-Fpo])</pre>
<p>Através das funções de RPC e OLE32 podemos concluir que se trata de uma chamada direta para uma interface COM. Bom, existem centenas de métodos e dezenas de interfaces nesse serviço, tornando mais fácil tentar desmontar a chamada inicial que o rpcrt4 faz ao nosso módulo.</p>
<pre>0:000&gt; ub <font color="#ff0000">77d79970</font>
rpcrt4!Invoke+0x20:
77d79960 fd              std
77d79961 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
77d79963 8b45f4          mov     eax,dword ptr [ebp-0Ch]
77d79966 50              push    eax
77d79967 669d            popf
77d79969 669d            popf
77d7996b 8b4508          mov     eax,<font color="#ff0000">dword ptr [ebp+8]</font>
77d7996e ffd0            call    eax</pre>
<p>Nossa função é obtida em ebp+8. Podemos obter esse endereço pelo campo <font color="#008000"><strong>ChildEBP </strong></font>da função em questão.</p>
<pre>0:000&gt; dd <font color="#008000">6645f788</font>+8 l1
6645f790  00406061
0:000&gt; uf 00406061
Service+0x6061:
00406061 55              push    ebp
00406062 8bec            mov     ebp,esp
00406064 81ecc8000000    sub     esp,0C8h
0040606a 833db09f410000  <font color="#0000ff">cmp     dword ptr [Service+0x19fb0 (00419fb0)],0</font>
00406071 751b            jne     Service+0x608e (0040608e)

<font color="#ff0000">Service+0x6073</font>:
00406073 6a00            push    0
00406075 6860514100      push    offset Service+0x15160 (00415160)
0040607a b9609e4100      mov     ecx,offset Service+0x19e60 (00419e60)
0040607f e822080000      call    Service+0x68a6 (004068a6)
00406084 8b4514          mov     eax,dword ptr [ebp+14h]
00406087 66c7002f00      mov     <font color="#008000">word ptr [eax],</font><font color="#0000ff">2Fh</font>
0040608c eb65            jmp     Service+0x60f3 (004060f3)

Service+0x608e:
0040608e 56              push    esi
0040608f 8b7508          mov     esi,dword ptr [ebp+8]
00406092 837e5200        cmp     dword ptr [esi+52h],0
00406096 7430            je      Service+0x60c8 (004060c8)

Service+0x6098:
00406098 8d8538ffffff    lea     eax,[ebp-0C8h]
0040609e 6830514100      push    offset Service+0x15130 (00415130)
004060a3 50              push    eax
004060a4 e85f4d0000      call    Service+0xae08 (0040ae08)
004060a9 59              pop     ecx
004060aa 59              pop     ecx
004060ab 6a00            push    0
004060ad 8d8538ffffff    lea     eax,[ebp-0C8h]
004060b3 50              push    eax
004060b4 b9609e4100      mov     ecx,offset Service+0x19e60 (00419e60)
004060b9 e8e8070000      call    Service+0x68a6 (004068a6)
004060be 8b4514          mov     eax,dword ptr [ebp+14h]
004060c1 66c7000a40      mov     word ptr [eax],400Ah
004060c6 eb2a            jmp     Service+0x60f2 (004060f2)

Service+0x60c8:
004060c8 6804010000      push    104h
004060cd 8d868c010000    lea     eax,[esi+18Ch]
004060d3 50              push    eax
004060d4 ff750c          push    dword ptr [ebp+0Ch]
004060d7 ff158c304100    call    dword ptr [Service+0x1308c (0041308c)]
004060dd 668b4510        mov     ax,word ptr [ebp+10h]
004060e1 8bce            mov     ecx,esi
004060e3 66894648        mov     word ptr [esi+48h],ax
004060e7 e892f2ffff      call    Service+0x537e (0040537e)
004060ec 8b4d14          mov     ecx,dword ptr [ebp+14h]
004060ef 668901          mov     word ptr [ecx],ax

Service+0x60f2:
004060f2 5e              pop     esi

Service+0x60f3:
004060f3 33c0            xor     eax,eax
004060f5 c9              leave
004060f6 c21000          ret     10h</pre>
<p>Note como a função <font color="#0000ff">compara algo com zero</font>. Caso não seja zero ela continua. Caso contrário ela vai para <font color="#ff0000">um ponto que chama uma função interna</font> e <font color="#008000">move um código de erro para um ponteiro recebido como parâmetro</font>, o que é muito normal, se lembrarmos que as funções COM de um programa em C devem retornar o código da chamada no retorno (S_OK) e o código de erro em um lResult da vida.</p>
<p><pre>STDMETHODIMP CService::<span style="color: #000000;">Open</span><span style="color: #000000; font-weight: bold;">&#40;</span>&lt;params&gt;, PLONG *pctReturn<span style="color: #000000; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">&#123;</span>
	<span style="color: #0000ff;">if</span><span style="color: #000000; font-weight: bold;">&#40;</span> DeuErrado<span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">&#41;</span> <span style="color: #000000; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">&#123;</span>
		*pctReturn = ERR_DEU_ERRADO;
		<span style="color: #0000ff;">return</span> S_OK;
	<span style="color: #000000; font-weight: bold;">&#125;</span>
	<span style="color: #006600;">//...</span>
<span style="color: #000000; font-weight: bold;">&#125;</span></pre></p>
<p>O código retornado é <font color="#0000ff">2Fh</font>, e agora temos uma boa pista para encontrar a localização no fonte. A primeira coisa é encontrar o define responsável por esse erro, o que exige um pouco de familiaridade com o sistema, pois não se trata aqui de um código Windows.</p>
<p><pre><span style="color: #006600;">#define OSRL_ERR	44	/* Data file serial number overflow */</span>
<span style="color: #006600;">#define KLEN_ERR	45	/* Key length exceeds MAXLEN parameter */</span>
<span style="color: #006600;">#define	FUSE_ERR	46	/* File number already in use */</span>
<span style="color: #006600;">#define FINT_ERR	47	/* database has not been initialized */</span>
<span style="color: #006600;">#define FMOD_ERR	48	/* Operation incompatible with type of file */</span>
<span style="color: #006600;">#define	FSAV_ERR	49	/* Could not save file */</span>
<span style="color: #006600;">#define LNOD_ERR	50	/* Could not lock node */</span></pre></p>
<p>Ótimo. 2F, para os leigos (leigos? o que vocês estão fazendo aqui?), é 47 em decimal, exatamente nosso código listado acima. Com esse define podemos agora procurar no código-fonte e analisar todas as funções que retornam esse código em seu início. Para nossa sorte, existe apenas uma.</p>
<p><pre>STDMETHODIMP CService::<span style="color: #000000;">Open</span><span style="color: #000000; font-weight: bold;">&#40;</span>BYTE *fileName, COUNT keyNo, COUNT *pctReturn<span style="color: #000000; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">&#123;</span>
	<span style="color: #0000ff;">char</span> szMsg<span style="color: #000000; font-weight: bold;">&#91;</span><span style="color: #000000;">200</span><span style="color: #000000; font-weight: bold;">&#93;</span>;
&nbsp;
	<span style="color: #006600;">// Verifica se o banco de dados foi inicializado</span>
	<span style="color: #0000ff;">if</span> <span style="color: #000000; font-weight: bold;">&#40;</span>!_Main.<span style="color: #000000;">m_bDBInitialized</span><span style="color: #000000; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">&#123;</span>
		_Main.<span style="color: #000000;">Log</span><span style="color: #000000; font-weight: bold;">&#40;</span><span style="color: #666666;">"Error opening file before database to be initialized."</span><span style="color: #000000; font-weight: bold;">&#41;</span>;
		*pctReturn = FINT_ERR;
		<span style="color: #0000ff;">return</span> S_OK;
	<span style="color: #000000; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #006600;">// Verifica se o arquivo j&aacute; foi aberto</span>
	<span style="color: #0000ff;">if</span> <span style="color: #000000; font-weight: bold;">&#40;</span>m_pData<span style="color: #000000; font-weight: bold;">&#41;</span>
	<span style="color: #000000; font-weight: bold;">&#123;</span>
		<span style="color: #0000ff;">sprintf</span><span style="color: #000000; font-weight: bold;">&#40;</span>szMsg, <span style="color: #666666;">"Error on open file <span style="color: #666666;">\"</span>%s<span style="color: #666666;">\"</span>. File already opened."</span><span style="color: #000000; font-weight: bold;">&#41;</span>;
		_Main.<span style="color: #000000;">Log</span><span style="color: #000000; font-weight: bold;">&#40;</span>szMsg<span style="color: #000000; font-weight: bold;">&#41;</span>;
		*pctReturn = ERR_BLABLABLA;
		<span style="color: #0000ff;">return</span> S_OK;
	<span style="color: #000000; font-weight: bold;">&#125;</span>
	<span style="color: #006600;">//...</span>
<span style="color: #000000; font-weight: bold;">&#125;</span></pre></p>
<p>Para confirmar que não estamos sonhando, podemos dar uma olhada no <font color="#ff0000">parâmetro </font>passado para a função <font color="#0000ff">Log </font>antes do código retornar. A memória deverá conter uma string idêntica a do código-fonte.</p>
<pre>Service+0x6073:
00406073 6a00            push    0
00406075 6860514100      push    offset Service+0x15160 (<font color="#ff0000">00415160</font>)
0040607a b9609e4100      mov     ecx,offset Service+0x19e60 (00419e60)
0040607f e822080000      call    <font color="#0000ff">Service+0x68a6</font> (004068a6)
00406084 8b4514          mov     eax,dword ptr [ebp+14h]
00406087 66c7002f00      mov     word ptr [eax],2Fh
0040608c eb65            jmp     Service+0x60f3 (004060f3)

0:000&gt; da <font color="#ff0000">00415160</font>
00415160  "Error opening file before databa"
00415180  "se to be initialized."</pre>
<p>E, agora sim, temos um bingo!</p>
<p><a href="http://annahinks.tumblr.com/post/176676889" title="Fonte da imagem "><img src="http://www.caloni.com.br/blog/wp-content/uploads/thats-a-bingo.jpg" alt="That’s a Bingo!" /></a></p>
<p>Mais para a frente em minha análise consegui encontrar o objeto pelo qual todas as threads esperavam. Não tive tanta sorte, pois se tratava de um mutex, e <a href="http://www.debuginfo.com/articles/easywindbg.html#debugdeadlocks" title="Sobre deadlock com mutex">mutexes não conseguem ser rastreados tão facilmente em user mode</a>. Mas isso não vem ao caso. O que tentei descrever aqui foi mais ou menos o processo que você deverá seguir caso tenha que analisar um binário compilado em outras vidas. Espero que você tenha tanta sorte quanto eu.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/como-achar-o-codigo-fonte-sem-simbolos/feed</wfw:commentRss>
		</item>
		<item>
		<title>Twitter, eu?</title>
		<link>http://www.caloni.com.br/blog/archives/twitter-eu</link>
		<comments>http://www.caloni.com.br/blog/archives/twitter-eu#comments</comments>
		<pubDate>Wed, 28 Jul 2010 02:02:10 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Devaneando]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/twitter-eu</guid>
		<description><![CDATA[Fico meio receoso de comentar aqui que, sim, eu tenho twitter, e, sim, sou praticante de mais uma das artes da vadiagem. Até porque se 5% dos meus tweets tiver alguma relação com o conteúdo desse blogue, é  muito. O resto são comentários sobre economia&#38;finanças, notícias aleatórias sobre alguma descoberta científica (ou não), dicas rápidas [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.caloni.com.br/blog/wp-content/uploads/twitter_bird.jpg" alt="twitter_bird.jpg" height="67" width="109" />Fico meio receoso de comentar aqui que, sim, eu tenho twitter, e, sim, sou praticante de mais uma das artes da vadiagem. Até porque se 5% dos meus tweets tiver alguma relação com o conteúdo desse blogue, é  muito. O resto são comentários sobre economia&amp;finanças, notícias aleatórias sobre alguma descoberta científica (ou não), dicas rápidas sobre cinema e sabe-lá-deus-o-que-mais.</p>
<p>E isso não vai mudar. É meu twitter pessoal. Aliás, meu próprio blogue também é pessoal, e é provável que no futuro ele que mude, e não o contrário.</p>
<p>Isso não quer dizer que vou deixar de ser programador. Acho que depois de dez anos programando sem parar essa opção não existe mais, pois as habilidades adquiridas já foram registradas no meu código genético. Só que, no meu caso, ser programador não evita que eu tenha uma porção de outros interesses e que me dedique a eles tanto quanto programação.</p>
<p>Dito isso, <a href="http://twitter.com/caloni" title="Meu Twitter">segue mais um ponteiro perdido pela rede</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/twitter-eu/feed</wfw:commentRss>
		</item>
		<item>
		<title>Breakpoints promíscuos</title>
		<link>http://www.caloni.com.br/blog/archives/breakpoints-promiscuos</link>
		<comments>http://www.caloni.com.br/blog/archives/breakpoints-promiscuos#comments</comments>
		<pubDate>Mon, 26 Jul 2010 19:57:32 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Depuração]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/breakpoints-promiscuos</guid>
		<description><![CDATA[Ontem falei sobre como "brincar" com os breakpoints promíscuos, ou seja, aqueles que topam qualquer processo. Isso
é muito simples de se fazer:
- Configure uma VM para bootar em kernel debug.
- Encontre um processo qualquer (vamos usar o notepad pra variar?).
- Reabra os símbolos de user mode nele.
- Defina um breakpoint em alguma DLL de user [...]]]></description>
			<content:encoded><![CDATA[<p>Ontem falei sobre como "brincar" com os breakpoints promíscuos, ou seja, aqueles que topam qualquer processo. Isso</p>
<p>é muito simples de se fazer:</p>
<p>- <a href="http://driverentry.com.br/blog/?p=433">Configure uma VM para bootar em kernel debug</a>.<br />
- Encontre um processo qualquer (vamos usar o notepad pra variar?).<br />
- Reabra os símbolos de user mode nele.<br />
- Defina um breakpoint em alguma DLL de user mode.</p>
<p>Como meus leitores são muito espertos foi partir para o momento após rodarmos um notepad.exe:</p>
<pre>kd&gt; !process 0 0 notepad.exe
PROCESS 81681be0  SessionId: 0  Cid: 0598    Peb: 7ffd7000  ParentCid: 0200
    DirBase: 08740260  ObjectTable: e18ee8d8  HandleCount:  29.
    Image: notepad.exe

kd&gt; .process /i 81681be0
You need to continue execution (press 'g' &lt;enter&gt;) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd&gt; g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
80527bdc cc              int     3
kd&gt; .reload /user
Loading User Symbols
.......................
kd&gt; bp user32!MessageBoxExW
kd&gt; g
Breakpoint 0 hit
USER32!MessageBoxExW:
001b:7e3a0838 8bff            mov     edi,edi
kd&gt; du poi(esp+8)
0007cfb8  "naoexistetralala.txt.Arquivo não"
0007cff8  " encontrado..Verifique se o nome"
0007d038  " do arquivo correto foi especifi"
0007d078  "cado."
kd&gt; ezu poi(esp+8) "Esse arquivo não existe! Mas é muito mané, não é mesmo?"
kd&gt; g</pre>
<p>O screenshot diz tudo:</p>
<p><a href="http://www.caloni.com.br/blog/wp-content/uploads/debug-notepad-kernel.png" title="Debug do notepad pelo kernel"><img src="http://www.caloni.com.br/blog/wp-content/uploads/debug-notepad-kernel.png" alt="Debug do notepad pelo kernel" /></a></p>
<p>Agora a parte mais divertida: experimente com outro notepad, ou com o explorer =)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/breakpoints-promiscuos/feed</wfw:commentRss>
		</item>
		<item>
		<title>Sétimo Encontro de Programadores C++</title>
		<link>http://www.caloni.com.br/blog/archives/setimo-encontro-de-programadores-c</link>
		<comments>http://www.caloni.com.br/blog/archives/setimo-encontro-de-programadores-c#comments</comments>
		<pubDate>Mon, 26 Jul 2010 02:44:31 +0000</pubDate>
		<dc:creator>Wanderley Caloni</dc:creator>
		
		<category><![CDATA[Devaneando]]></category>

		<category><![CDATA[Depuração]]></category>

		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://www.caloni.com.br/blog/archives/setimo-encontro-de-programadores-c</guid>
		<description><![CDATA[Mais um fim-de-semana no ócio e na vadiagem. Tenho que manter minhas qualidades de bom programador que sou: preguiçoso, impaciente e pretensioso.
Mas nem por isso deixei de terminar uma primeira versão do aplicativo que irei usar como base na minha palestra do nosso próximo encontro C++: Crash Dump Analysis. Se alguém tiver dicas de quais [...]]]></description>
			<content:encoded><![CDATA[<p>Mais um fim-de-semana no ócio e na vadiagem. Tenho que manter minhas <a href="http://c2.com/cgi/wiki?LazinessImpatienceHubris">qualidades de bom programador</a> que sou: preguiçoso, impaciente e pretensioso.</p>
<p>Mas nem por isso deixei de terminar uma primeira versão do aplicativo que irei usar como base na minha palestra do nosso próximo <a href="http://www.ccppbrasil.org/wiki/Grupo:Encontro_VII">encontro C++</a>: <a href="http://www.caloni.com.br/blog/wp-content/uploads/crashdumpanalysis.7z" title="CrashDumpAnalysis">Crash Dump Analysis</a>. Se alguém tiver dicas de quais os problemas mais difíceis do Universo para analisar em um dump de memória, comente a respeito e veremos o que dá pra fazer.</p>
<p style="text-align: center"><img src="http://www.caloni.com.br/blog/wp-content/uploads/crash-dump.png" alt="crash-dump.png" /></p>
<p>Enquanto isso, continuo descobrindo maravilhas do WinDbg. Essa semana fiquei brincando de colocar breakpoint em user-mode, mas depurando o kernel, como fizeram <a href="http://blogs.msdn.com/b/ntdebugging/archive/2010/07/20/debugging-services-startup-in-svchost-from-a-kernel-mode-debug-session.aspx">os rapazes do Ntdebugging</a>. A conclusão é que ele vale para todos os aplicativos abertos. Tente com o MessageBox!</p>
<pre>!process 0 0 notepad.exe
.reload /user
bp user32!MessageBoxW</pre>
<p>Mas devaneio. Talvez outra boa qualidade de um bom programador.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.caloni.com.br/blog/archives/setimo-encontro-de-programadores-c/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
