-
Notifications
You must be signed in to change notification settings - Fork 0
/
2008-10.html
492 lines (370 loc) · 32.2 KB
/
2008-10.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
<!DOCTYPE html>
<html lang="en-us" dir="ltr" itemscope itemtype="http://schema.org/Article">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Blogue do Caloni</title>
<meta name="author" content="Caloni" />
<meta name="generator" content="txt2blog 0.0.1">
<meta property="og:title" content="Blogue do Caloni"/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="http://www.caloni.com.br"/>
<meta property="og:image" content="/img/about-brand.png"/>
<meta property="og:description" content="Write for computers, people and food."/>
<link href="/index.xml" rel="feed" type="application/rss+xml" title="Blogue do Caloni"/>
<link rel="stylesheet" type="text/css" href="/css/custom.css"/>
<link rel="stylesheet" type="text/css" href="/css/jquery-ui.css"/>
<script src="/js/jquery-1.12.4.js"></script>
<script src="/js/jquery-ui.js"></script>
<script src="/js/copy_clipboard.js"></script>
<script>
var quick_search_posts = [
];
</script>
<script src="/js/quick_search.js"></script>
<script src="/js/list.js"></script>
<link rel="icon" href="/img/favicon.ico"/>
</head>
<body style="min-height:100vh;display:flex;flex-direction:column">
<nav class="navbar has-shadow is-white"
role="navigation" aria-label="main navigation">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item" href="months.html">
<div class="is-4"><b>caloni::2008-10</b></div>
</a>
</div>
</div>
</nav>
<div class="container">
<div class="column">
<div style="min-height:56vh">
<div style="padding-bottom: 1em;"></div>
<ul style="list-style: none;">
<li><small><a href="2008-10.html#o_que_acontece_com_um_programador_com_pressa">O que acontece com um programador com pressa</a></small></li>
<li><small><a href="2008-10.html#impressoes_do_quinto_encontro_de_ccpp">Impressões do quinto encontro de CCPP</a></small></li>
<li><small><a href="2008-10.html#como_usar_wtl_com_o_atl_do_ddk">Como usar WTL com o ATL do DDK</a></small></li>
<li><small><a href="2008-10.html#a_alca_dentro_do_fio_gerou_um_bloqueio_da_morte">A Alça Dentro do Fio Gerou um Bloqueio da Morte</a></small></li>
<li><small><a href="2008-10.html#como_funciona_o_psexec">Como funciona o PsExec</a></small></li>
</ul>
<span id="o_que_acontece_com_um_programador_com_pressa" title="O que acontece com um programador com pressa"/></span>
<section id="section_o_que_acontece_com_um_programador_com_pressa">
<p class="title"><a href="2008-10.html#o_que_acontece_com_um_programador_com_pressa">#</a> O que acontece com um programador com pressa</p>
<span class="title-heading">Caloni, 2008-10-05<a href="2008-10.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_o_que_acontece_com_um_programador_com_pressa')"><sup>[copy]</sup></a></span>
<p>Eu já sabia, mas é lógico que não ia falar.</p>
<p>Há um tempo atrás um rapaz me pediu para responder uma série de questões sobre a carreira de programador C++. Era um rapaz empolgado com a idéia de aprender a linguagem em seis meses, com um roteiro, cronograma e um blogue recém-criados.</p>
<p>Como quase toda uma geração do imediatismo, aconteceu o inevitável: o blogue já não é atualizado há quase dois meses e toda aquela empolgação do começo deve ter virado fumaça assim que a pessoa vira a esquina e aparece uma coisa nova para fazer. E daí surgem as desculpas, o blá-blá-blá de todos aqueles que nunca têm tempo.</p>
<p>Eu sou um deles, mas de vez em quando atualizo esse meu espacinho =)</p>
<p>Na experiência de vida que tenho com todas aquelas idéias mirabolantes que as pessoas possuem de fazer alguma coisa, seja um software, aprender algo novo, ou até criar uma rotina qualquer, eu diria que quase todas, se não todas, falharam.</p>
<p>É natural que no começo, quando a idéia brota, e mais idéias formentam a idéia original, o empolgamento nos dá a falsa impressão que podemos fazer isso facilmente, e que é só planejar, ter vontade e ir em frente que conseguimos. É claro que toda essa impressão muda com o passar do tempo, principalmente para aquelas pessoas que possuem muitas idéias em muito pouco tempo, algo que acontece bastante com programadores, mas que em geral afeta todo mundo.</p>
<p>Em se tratando de software, a primeira coisa que deve ser feita, sempre, é planejar as tarefas visíveis a serem feitas para esboçar um panorama possível para o futuro do projeto. Eu disse possível no sentido de realizável.</p>
<p>O segundo passo é esquecer esse negócio de realizável, cair na real e encarar os fatos: o mundo não é perfeito. Comece a colocar defeitos no cronograma, tentar imaginar o que vai sair errado e, principalmente, conhecer você mesmo e as pessoas envolvidas para ter a real expectativa do que pode ser feito em quanto tempo.</p>
<p>Após jogar água fria o suficiente (às vezes são necessários muitos baldes) sobre suas idéias novas e excitantes, temos um panorama um pouco mais preciso, mais realista e, agora sim, passível de ser feito e acontecer de verdade.</p>
<p>Só que ainda não acabou.</p>
<p>É claro que isso tudo é o começo do projeto. Após a primeira semana, o primeiro mês, o segundo mês e o segundo semestre as atividades devem ser revistas e reprojetadas. Mais uma vez entra a regrinha da água fria. Não é porque deu errado no começo que não pode dar mais errado ainda no final.</p>
<p>Esse pequeno chamado foi apenas um reforço do apelo que Rodrigo Strauss fez em nosso último encontro de C++. Nosso grupo precisa de mais pessoas que escrevam algo. Portanto, façam blogues, mas não os deixem desgarrados!</p>
</section><hr/>
<span id="impressoes_do_quinto_encontro_de_ccpp" title="Impressões do quinto encontro de CCPP"/></span>
<section id="section_impressoes_do_quinto_encontro_de_ccpp">
<p class="title"><a href="2008-10.html#impressoes_do_quinto_encontro_de_ccpp">#</a> Impressões do quinto encontro de CCPP</p>
<span class="title-heading">Caloni, 2008-10-07 <a href="ccppbr.html">ccppbr</a><a href="2008-10.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_impressoes_do_quinto_encontro_de_ccpp')"><sup>[copy]</sup></a></span>
<p>Pois é, passou, acabou... e foi muito bom!</p>
<p>E dessa vez me abstenho de fazer os comentários de sempre, visto que já está rolando uma discussão muito produtiva sobre o resultado desse último encontro, opiniões que, sinceramente, já refletem os pensamentos de todos que participaram desse magnânimo encontro de usuários.</p>
</section><hr/>
<span id="como_usar_wtl_com_o_atl_do_ddk" title="Como usar WTL com o ATL do DDK"/></span>
<section id="section_como_usar_wtl_com_o_atl_do_ddk">
<p class="title"><a href="2008-10.html#como_usar_wtl_com_o_atl_do_ddk">#</a> Como usar WTL com o ATL do DDK</p>
<span class="title-heading">Caloni, 2008-10-15 <a href="coding.html">coding</a><a href="2008-10.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_como_usar_wtl_com_o_atl_do_ddk')"><sup>[copy]</sup></a></span>
<p>Eu simplemente não entendo a organização dos cabeçalhos e fontes dos SDKs da Microsoft. Houve uma vez em que o <a href="http://www.1bit.com.br/content.1bit/weblog/sopa_de_letrinhas_ATL">ATL</a> era distribuído junto com o SDK, e dessa forma conseguíamos usar o <a href="http://www.1bit.com.br/content.1bit/weblog/sopa_de_letrinhas_wtl">WTL</a> sem ônus. Porém, um belo dia, isso é retirado do pacote, para tristeza dos que já haviam convertido a biblioteca de janelas para fonte aberto.</p>
<p>No entanto, num belo dia, qual não foi minha surpresa ao notar umas pastinhas chamadas atl21, atl30 e atl71 dentro da distribuição do WDK (o finado DDK, renomeado sabe-se-lá-por-quê)? Pelo visto, tem alguém arrastando coisa errada pra onde não devia nos instaladores de Seattle. Esses estagiários!</p>
<img src="img/como_usar_wtl_com_o_atl_do_ddk_OoiV6X7.png"/>
<p>O fato é que eles fizeram isso, e agora é possível ter o WTL mais novo compilado com o WDK. E nem é tão difícil assim.</p>
<p>A primeira coisa a fazer é obter o tal do WDK. Para variar um pouco, agora existe (existia) um processo de registro antes de obter acesso ao _download_, mais ou menos nos termos da Borland para baixar o C++ Builder ou Turbo Pascal ou o Developer Studio.</p>
<p><blockquote>Aliás, para os que baixaram esses produtos gratuitos da Borland versão C++ e não funcionou em algumas máquinas, como foi o meu caso, está disponível para baixar uma versão mais nova; dessa vez não vi nenhum problema na compilação e depuração. Ainda.</blockquote></p>
<p>Após instalado, em qualquer lugar da sua escolha, configure no seu Visual Studio o caminho de onde se encontra a pasta atl71 (ou a 30, ou a 21). Aproveite também para colocar a pasta do WTL e o diretório de LIBs:</p>
<img src="img/como_usar_wtl_com_o_atl_do_ddk_TJyNrlE.png"/>
<img src="img/como_usar_wtl_com_o_atl_do_ddk_VLryS9L.png"/>
<p>Isso vai fazer com que pelo menos os exemplos que vêem com o WTL compilem.</p>
<p>No entanto, você verá o seguinte erro durante a compilação dos recursos:</p>
<pre>
------ Build started: Project: MTPad, Configuration: Debug Win32 ------
Compiling resources...
Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
Copyright (C) Microsoft Corporation. All rights reserved.
Linking...
CVTRES : fatal error CVT1100: <font color="#ff0000">duplicate resource</font>. type:MANIFEST, name:1, language:0x0409
LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt
Build log was saved at "file://c:\Lng\WTL\Samples\MTPad\Debug\BuildLog.htm"
MTPad - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
</pre>
<p>Para resolver esse problema, remova a inclusão do arquivo de manifesto no arquivo RC:</p>
<pre>
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""atlres.h""\r\n"
"\0"
END
<font color="#ff0000">3 TEXTINCLUDE DISCARDABLE
BEGIN
"CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""res\\\\MTPad.exe.manifest""\r\n"
"\0"
END</font>
#endif // APSTUDIO_INVOKED
...
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
<font color="#ff0000">CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "res\\MTPad.exe.manifest"</font>
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
</pre>
<p>Depois dessa alteração, deve ainda existir o seguinte erro de linquedição:</p>
<pre>
------ Build started: Project: MTPad, Configuration: Debug Win32 ------
Compiling resources...
Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
Copyright (C) Microsoft Corporation. All rights reserved.
Linking...
<font color="#ff0000">mtpad.obj : error LNK2019: unresolved external symbol
"void * __stdcall ATL::__AllocStdCallThunk(void)" (bla bla bla)
mtpad.obj : error LNK2019: unresolved external symbol
"void __stdcall ATL::__FreeStdCallThunk(void *)" (bla bla bla)
</font>.\Debug/MTPad.exe : fatal error LNK1120: 2 unresolved externals
Build log was saved at "file://c:\Lng\WTL\Samples\MTPad\Debug\BuildLog.htm"
MTPad - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
</pre>
<p>Esse problema ocorre porque as funções de alocação e desalocação de memória da ATL estão em outra LIB que os exemplos da WTL desconhecem. Para resolver, basta incluir essa nova dependência:</p>
<pre>
#pragma comment(lib, "<strong>atlthunk.lib</strong>")
</pre>
<p>E pronto! Agora temos todo o poder das 500 milhões de classes da ATL aliadas à ilimitada flexibilidade das classes de janelas da WTL.</p>
<h4>Para aprender a usar WTL</h4>
<pre>
</pre>
<p> * <a href="posts.html?q=Explicando a sopa de letrinhas da programação C/C++ para Windows: WTL">Explicando a sopa de letrinhas da programação C/C++ para Windows: WTL</a></p>
<p> * <a href="http://www.codeproject.com/KB/wtl/wtl4mfc1.aspx">WTL for MFC Programmers</a></p>
</section><hr/>
<span id="a_alca_dentro_do_fio_gerou_um_bloqueio_da_morte" title="A Alça Dentro do Fio Gerou um Bloqueio da Morte"/></span>
<section id="section_a_alca_dentro_do_fio_gerou_um_bloqueio_da_morte">
<p class="title"><a href="2008-10.html#a_alca_dentro_do_fio_gerou_um_bloqueio_da_morte">#</a> A Alça Dentro do Fio Gerou um Bloqueio da Morte</p>
<span class="title-heading">Caloni, 2008-10-21 <a href="coding.html">coding</a><a href="2008-10.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_a_alca_dentro_do_fio_gerou_um_bloqueio_da_morte')"><sup>[copy]</sup></a></span>
<p>Estava folheando um livro fenomenal que meu amigo havia pedido emprestado para ler quando me deparei com algumas traduções no mínimo curiosas. O exemplar em questão era o primeiro Windows Internals, publicado após o lançamento da primeira versão do Windows NT, uma plataforma escrita (quase) inteiramente do zero para suplantar as versões 9x (Windows 95 e 98), que herdaram do DOS algumas partes indesejáveis em sistemas operacionais modernos.</p>
<p>Sabe-se lá por que essa edição foi traduzida. É interessante notar que naquela época foi dado um tratamento especial a alguns termos e conceitos já comuns no dia-a-dia do programador americano, apesar de quase nenhum desses termos ter se mantido em sua versão original. Os exemplos mais gritantes são as threads (fios ou linhas), os dead locks (bloqueios da morte) e os handles (alças). Apesar de não ter nada contra traduzir termos do inglês para português (e vice-versa) algumas coisas incomodam em tradução de livros técnicos.</p>
<p>Um bom exemplo são ponteiros. Ler em um dado capítulo "(...) é muito importante inicializar seus ponteiros antes de usá-los" para, depois de nos acostumarmos com o termo, ler em outro capítulo "(...) sabe-se que a pior desgraça para um programador C são os famigerados apontadores selvagens". Você resolveria esse tipo de problema definindo um vocabulário em comum com todo o livro (importantíssimo se ele está sendo traduziro por mais de uma pessoa) e ainda informaria o leitor qual o termo original, caso ele precise pesquisar sobre ele fora do livro. Com essa informação, que pode ser usada apenas nos primeiros usos da palavra ou em um glossário à parte, agradaria gregos e troianos: "os ponteiros em C (pointers) são um recurso rico e necessário para a escrita de programas de baixo/médio nível".</p>
<p>Um exemplo notável é o famoso livro de algoritmos em C da O'Reilly, que mesmo na nova edição com uma errata de 49 itens foi possível detectar mais erros. Um exemplo que me lembro era de uma função do algoritmo bitree. Nele havia uma variável com o nome orig que três linhas abaixo estava "traduzida" para original. É importante aqui diferenciar que no original não consta esse erro da troca do nome da variável.</p>
<p>Isso acaba sendo pior do que não colocar a versão em inglês, pois dá a impressão que não existe significado a ser explicado. Por exemplo, ver antes do capítulo sobre threads a passagem "... quando um fio espera o outro e vice-versa, acontece o terrível bug da trava da morte". Para quem não descobriu o que foi escrito no original, se trata de duas threads (fios) causando um deadlock (trava da morte), cujo termo inclusive é usado no seu original na <a href="https://pt.wikipedia.org/wiki/Deadlock">Wikipédia em português</a>.</p>
<p>Esses exemplos, salvo o exemplo do livro de algoritmos, foram criados para ilustrar os tipos de erros mais comuns em traduções de livros técnicos, e não estão relacionados com qualquer livro em específico. Então o que era inicialmente para ajudar as pessoas que estão iniciando alguns conceitos acaba por prejudicar ainda mais o aprendizado, gerando aquele tipo de confusão que só com ajuda extra (internet, professor, colega) pode ser resolvida.</p>
<p>Assim como no vocabulário comum corrente, em que existem palavras dificilmente adaptáveis ou traduzíveis em um termo comum, como shopping e show, no meio técnico brotam as mais variadas expressões "estrangeirísticas". Algumas são muito difíceis de encontrar seu primo lusófono, como link e login. Outros, no entanto, exageram um pouco as coisas, a ponto de conjugarmos um verbo em inglês usando nosso sistema gramatical: se você "stopar" o "debugador" vai "crashear" todo o sistema, porque esse software tá "bugado"! <a href="posts.html?q=1">1</a></p>
<p>O fato é que não há escapatória para quem trabalha nessa área, e no fundo isso é uma coisa boa, pois é da leitura técnica em inglês que podemos estender o nosso conhecimento além das barreiras do ponto com ponto br e encontrar conteúdo extremamente interessante (e inédito em nossa língua) para aprender. Se não estivéssemos abarrotados de estrangeirismos talvez fosse um pouco mais difícil fazer o switch entre essas duas linguagens.</p>
<p><a href="posts.html?q=1">1</a> Ironicamente 12 anos depois deste artigo ser escrito o verbo bugar virou uma gíria corrente entre jovens.</p>
</section><hr/>
<span id="como_funciona_o_psexec" title="Como funciona o PsExec"/></span>
<section id="section_como_funciona_o_psexec">
<p class="title"><a href="2008-10.html#como_funciona_o_psexec">#</a> Como funciona o PsExec</p>
<span class="title-heading">Caloni, 2008-10-29 <a href="coding.html">coding</a><a href="2008-10.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_como_funciona_o_psexec')"><sup>[copy]</sup></a></span>
<p>Semana passada precisei reproduzir o comportamento da ferramenta PsExec em um projeto, o que me fez sentir alguma nostalgia dos tempos em que eu fazia <a href="posts.html?q=engenharia reversa">engenharia reversa</a> todo dia. Este breve relato (espero) reproduz os passos que segui para descobrir o que esse programa tão útil quanto perigoso faz.</p>
<h4>Dados conhecidos</h4>
<p>Sabe-se que o PsExec consegue **executar um programa remotamente**, ou seja, de uma máquina para outra, outra essa que chamaremos de **máquina-alvo**. O programa a ser executado geralmente deve estar disponível na própria máquina-alvo (condição ideal). Além da simples execução, para aplicativos console ele permite ainda a interação como se estivéssemos executando o programa remoto em nossa própria máquina local. Ele consegue isso redirecionando sua entrada e saída, o que o torna, como nos descreve o próprio autor, um "_telnet light_":</p>
<pre>
psexec \\maquina-alvo [-u admin-na-maquina-alvo] cmd.exe
</pre>
<p>Além desse comportamento já muito útil ainda existe um bônus que se trata de especificar um executável local que será **copiado remotamente** para a máquina-alvo e executado. **Esse é o comportamento que espero imitar**:</p>
<pre>
psexec \\maquina-alvo [-c c:\tests\myprogram.exe] [-u admin-na-maquina-alvo]
PsExec v1.72 - Execute processes remotely Copyright (C) 2001-2006 Mark Russinovich
Sysinternals - www.sysinternals.com
Microsoft Windows XP [versão 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
</pre>
<p>No teste acima o **myprogram.exe** é somente o **cmd.exe** renomeado. Um teste básico =)</p>
<h4>Primeiro passo: reproduzir o comportamento analisado e coletar pistas</h4>
<p>Já fizemos isso logo acima. Se trata apenas de observar o programa funcionando. Ao mesmo tempo em que entendemos seu _modus operandi_ coletamos pistas sobre suas entranhas. No caso do PsExec, que faz coisas além-mar, como redirecionar os _pipes_ de entrada/saída de um programa console, iremos checar a existência de algum serviço novo na máquina-alvo e arquivos novos que foram copiados, além de opcionalmente dar uma olhada no registro. Ferramentas da própria SysInternals como <a href="posts.html?q=Process Explorer">Process Explorer</a> e <a href="posts.html?q=Process Monitor">Process Monitor</a> também são úteis nessa análise inicial.</p>
<img src="img/como_funciona_o_psexec_lCf4KiT.png"/>
<p>Como podemos ver, um serviço com o nome de PsExec foi criado na máquina-alvo. Se procurarmos saber o caminho do arquivo que corresponde a esse serviço, tanto pelo Process Explorer ou o Service Manager, descobriremos que se trata de um arquivo no diretório do windows chamado **psexecsvc.exe**.</p>
<img src="img/como_funciona_o_psexec_qo6PZWS.png"/>
<img src="img/como_funciona_o_psexec_2sSwUA9.png"/>
<p>Se o arquivo existe nessa pasta, então é óbvio que alguém o copiou. Resta saber **como**.</p>
<h4>Segundo passo: acompanhar o processo lentamente</h4>
<p>Nessa segunda fase, podemos refazer o comportamento esperado inúmeras vezes, coletando dados e pensando a partir dos dados obtidos. Para esse caso, como quase todos que analiso, vou usar o nosso amigo <a href="posts.html?q=WinDbg">WinDbg</a>. Para isso, como tenho sempre minhas ferramentas disponíveis no ambiente onde trabalho, basta digitar "windbg" antes do comando anterior e **dar uma olhada em algumas APIs-chave**, como a criação/abertura de arquivos e a criação de serviços. Note que é importante fazer isso em um **escopo limitado** para não perdermos horas de análise. Descobrir coisas como, por exemplo, que as ações do PsExec só começam a ser executadas após a digitação da senha do usuário, pode ajudar, pois daí só começo minha análise a partir desse ponto.</p>
<pre>
windbg psexec \\maquina-alvo -u admin cmd.exe
PsExec v1.72 - Execute processes remotely
Copyright (C) 2001-2006 Mark Russinovich
Sysinternals - www.sysinternals.com
Password:
ntdll!DbgBreakPoint:
7c90120e cc int 3
0:001> bp kernel32!CreateFileW
0:001> bp advapi32!CreateServiceW
0:001> g
Connecting to maquina-alvo...
Breakpoint 0 hit
eax=40150000 ebx=0011ee90 ecx=00000000 edx=00005078 esi=7c80932e edi=0011eeb0
eip=7c8107f0 esp=0011ee70 ebp=0011eed0 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
kernel32!CreateFileW:
7c8107f0 8bff mov edi,edi
0:000> du poi(@esp+4)
0011ee90 <font color="#0000ff">"\\.\PIPE\wkssvc"</font>
0:000> k 50 // pilha muito grande!
ChildEBP RetAddr
0011ee6c 77dc4b92 kernel32!CreateFileW
0011eed0 77dc4369 RPCRT4!NMP_Open+0x17a
0011ef1c 77dc48d3 RPCRT4!OSF_CCONNECTION::TransOpen+0x5e
0011ef70 77dc4a5d RPCRT4!OSF_CCONNECTION::OpenConnectionAndBind+0xbc
0011efb4 77dc49ac RPCRT4!OSF_CCALL::BindToServer+0x104
0011f018 77dbfdbc RPCRT4!OSF_BINDING_HANDLE::AllocateCCall+0x2b6
0011f048 77db8a01 RPCRT4!OSF_BINDING_HANDLE::NegotiateTransferSyntax+0x28
0011f060 77db8a38 RPCRT4!I_RpcGetBufferWithObject+0x5b
0011f070 77db906d RPCRT4!I_RpcGetBuffer+0xf
0011f080 77e3460b RPCRT4!NdrGetBuffer+0x28
0011f460 5bcb9d7c RPCRT4!NdrClientCall2+0x195
0011f474 5bcb9d1e NETAPI32!NetrWkstaGetInfo+0x1b
0011f4bc 71c78cc2 NETAPI32!NetWkstaGetInfo+0x38
0011f4e0 71c78a75 NETUI1!WKSTA_10::I_GetInfo+0x21
0011f4e8 71be1843 NETUI1!NEW_LM_OBJ::GetInfo+0x1c
0011fadc 71be31aa ntlanman!CheckLMService+0x3d
00120464 71be3058 ntlanman!AddConnection3Help+0x3e
0012118c 71be2e29 ntlanman!AddConnectionWorker+0x37c
001211b0 71ae461a ntlanman!NPAddConnection3+0x1f
001211d8 71ae45ac MPR!CUseConnection::TestProviderWorker+0x47
00121aa8 71ae2445 MPR!CUseConnection::TestProvider+0x62
00121b08 71ae431d MPR!CRoutedOperation::GetResult+0x10f
00121da4 71ae2348 MPR!CUseConnection::GetResult+0x180
00121ddc 71ae22fd MPR!CMprOperation::Perform+0x4d
00121de8 71ae4505 MPR!CRoutedOperation::Perform+0x22
00121e98 71ae50f0 MPR!WNetUseConnectionW+0x58
*** WARNING: Unable to verify checksum for image00400000
*** ERROR: Module load completed but symbols could not be loaded for image00400000
00121ec0 00401796 <font color="#0000ff">MPR!WNetAddConnection2W</font>+0x1c
WARNING: Stack unwind information not available. Following frames may be wrong.
001225d0 0032002e image00400000+0x1796
001225d4 0030002e 0x32002e
001225d8 0034002e 0x30002e
001225dc 00000000 0x34002e
</pre>
<p>Uma rápida busca no Google nos informa que o _pipe _querendo ser aberto pertence à lista de _pipes _que estão sempre disponíveis nas máquinas para responder às requisições do sistema. São importantes para a **comunicação entre processos** (IRP, _Inter Process Communication_). No entanto, quem usa esse pipe é o sistema, e ele foi chamado, como pudemos ver, pela função WNetAddConnection2W.</p>
<p>Se analisarmos mais a fundo a pilha de chamadas conseguiremos dar um olhada nos parâmetros passados. Para isso existe a opção de mostrar os argumentos passados para as funções ao exibir a pilha:</p>
<pre>
0:000> kv 50
ChildEBP RetAddr Args to Child
0011ee6c 77dc4b92 0011ee90 c0000000 00000003 kernel32!CreateFileW (FPO:
0011eed0 77dc4369 00147140 001463f8 005b4b46 RPCRT4!NMP_Open+0x17a (FPO:
...
00121e98 71ae50f0 00000000 00121ee4 004182a0 MPR!WNetUseConnectionW+0x58 (FPO: [Non-Fpo])
*** WARNING: Unable to verify checksum for image00400000
*** ERROR: Module load completed but symbols could not be loaded for image00400000
00121ec0 00401796 <font color="#0000ff">00121ee4 </font><font color="#000000">004182a0 004139e0</font><font color="#000000"> </font>MPR!WNetAddConnection2W+0x1c (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
001225d0 0032002e 0030002e 0034002e 00000030 image00400000+0x1796
001225d4 0030002e 0034002e 00000030 00000000 0x32002e
001225d8 0034002e 00000030 00000000 00000000 0x30002e
001225dc 00000000 00000000 00000000 00000000 0x34002e
0:000> db <font color="#0000ff">00121ee4</font>
00121ee4 00 00 00 00 00 00 00 00-00 00 00 00 03 00 00 00 ................
00121ef4 e2 1e 12 00 04 1f 12 00-00 00 00 00 00 00 00 00 ................
00121f04 5c 00 5c 00 31 00 30 00-2e 00 32 00 2e 00 30 00 <font color="#0000ff">\.\.1.0...2...0.</font>
00121f14 2e 00 34 00 30 00 5c 00-49 00 50 00 43 00 24 00 <font color="#0000ff">..4.0.\.I.P.C.$.</font>
00121f24 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00121f34 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00121f44 cc da 90 7c c8 2d 91 7c-ec 07 00 00 88 1f 12 00 ...|.-.|........
00121f54 88 1f 12 00 00 00 00 00-f2 20 12 00 e0 24 12 00 ......... ...$..
</pre>
<p>Ele tenta abrir uma conexão com a máquina-alvo em seu compartilhamento de **IPC**, que como já vimos serve para comunicação entre processos, até entre máquinas distintas. Dessa forma, descobrimos um dos pontos importantes no funcionamento do PsExec: ele usa o nome e senha fornecidos para abrir uma comunicação remota no compartilhamento IPC$.</p>
<p>Depois sugem várias paradas ao CreateFile, de maneira que a melhor forma de acompanhar isso é colocando um "_dumpezinho_" de memória na sua parada:</p>
<pre>
0:000> bp kernel32!CreateFileW "<font color="#0000ff">du poi(@esp+4)</font>"
breakpoint 0 redefined
0:000> g
0011ee90 "\\.\PIPE\wkssvc"
eax=40150000 ebx=0011ee90 ecx=00000000 edx=00005d6e esi=7c80932e edi=0011eeb0
eip=7c8107f0 esp=0011ee70 ebp=0011eed0 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
kernel32!CreateFileW:
7c8107f0 8bff mov edi,edi
0:000> g
0011f474 "\\.\PIPE\wkssvc"
eax=40160000 ebx=0011f474 ecx=00000000 edx=00005d77 esi=7c80932e edi=0011f494
eip=7c8107f0 esp=0011f454 ebp=0011f4b4 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
kernel32!CreateFileW:
7c8107f0 8bff mov edi,edi
0:000> g
0011f210 "\\.\PIPE\wkssvc"
eax=40160000 ebx=0011f210 ecx=00000000 edx=00005d7a esi=7c80932e edi=0011f230
eip=7c8107f0 esp=0011f1f0 ebp=0011f250 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
kernel32!CreateFileW:
7c8107f0 8bff mov edi,edi
0:000> g
0012213c <font color="#0000ff">"\\10.2.0.40\ADMIN$\PSEXESVC.EXE"</font>
eax=00122090 ebx=00000003 ecx=00000000 edx=009300d0 esi=00000080 edi=ffffffff
eip=7c8107f0 esp=00122064 ebp=001220ac iopl=0 nv up ei pl nz ac po cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000213
kernel32!CreateFileW:
7c8107f0 8bff mov edi,edi
</pre>
<p>Muito bem! Chegamos a mais um ponto importante de nossa análise: o psexecsvc.exe é copiado através do compartilhamento **ADMIN$** remotamente (diretório c:\windows). Esse compartilhamento se torna acessível, uma vez que uma conexão autenticada já foi aberta. Se listarmos as conexões existentes, veremos o compartilhamento IPC$ aberto:</p>
<pre>
>net use
Novas conexões serão lembradas.
Status Local Remoto Rede
-------------------------------------------------------------------------------
OK <font color="#0000ff">\\10.2.0.40\IPC$</font> Rede Microsoft Windows
Comando concluído com êxito.
>
</pre>
<p>Também podemos notar que, enquanto estamos parados depurando o processo psexec.exe, temos acesso ao compartilhamento admin$:</p>
<img src="img/como_funciona_o_psexec_vBGHXoC.png"/>
<p>A análise desses fatos demonstra como é importante fazer as coisas, pelo menos na fase "iniciante", bem lentamente, e entender a **mudança de estado** durante o processo. Nem sempre isso é possível, é verdade, ainda mais quando estamos falando de análise de kernel. Mas, quando as condições permitem, vale a pena pensar antes de fazer.</p>
<p>Voltando à analise: temos direitos remotos nessa máquina. Dessa forma, fica fácil criar um serviço remotamente, que é o que faz o nosso amigo PsExec:</p>
<pre>
0:000> g
Breakpoint 1 hit
eax=00410870 ebx=00410870 ecx=00147a68 edx=00410844 esi=00410844 edi=00147a68
eip=77fb7381 esp=001224e4 ebp=001228dc iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
ADVAPI32!CreateServiceW:
77fb7381 6a20 push 20h
0:000> du poi(@esp+8)
00410870 "PSEXESVC"
0:000> du poi(@esp+8*4)
001228dc "%SystemRoot%\PSEXESVC.EXE"
</pre>
<p>Pronto. Isso era tudo que precisava para conseguir reproduzir seu comportamento. Agora posso fazer isso programando ou até manualmente:</p>
<pre>
C:\Tests>net use \\10.2.0.40\ipc$ /user:admin
A senha ou o nome de usuário é inválido para \\10.2.0.40\ipc$.
Digite a senha para que 'admin' se conecte a '10.2.0.40':
Comando concluído com êxito.
C:\Tests>net use
Novas conexões serão lembradas.
Status Local Remoto Rede
-------------------------------------------------------------------------------
OK \\10.2.0.40\ipc$ Rede Microsoft Windows
Comando concluído com êxito.
C:\Tests>copy myprogram.exe \\10.2.0.40\admin$
1 arquivo(s) copiado(s).
C:\Tests>sc \\10.2.0.40 create MyProgram binPath= %systemroot%\myprogram.exe
[SC] CreateService SUCCESS
</pre>
<p>O resto do comportamento, como o redirecionamento de entrada e saída e execução do processo na conta especificada, embora muito interessante, não me interessa de imediato. Quem sabe interesse a você, e não tenhamos uma continuação dessa análise em um outro blogue de "desmontagem" por aí =)</p>
</section><hr/>
<span style="float: left;">
<a href="2008-09.html">[2008-09]</a>
<a href="2008-11.html">[2008-11]</a>
</span>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
</div>
</footer>
</body>
</html>