# Aprimorando cafezes (sobre blends)
Caloni, 2023-06-05 cooking coffee [up] [copy]Eu até gostei dos grãos que trouxe do The Cofee após o incidente em busca de café. Ele é daquela série de cítricos que não lembra muito café e tem pouco corpo. No entanto, chega uma hora que mesmo com apenas 250g enjoa. Então lembrei que ainda tenho o café de Tiradentes da viagem do começo do ano, o Tamandaré, um café tipicamente mineiro: encorpado e torrado demais.
Então resolvi juntar os dois.
Para isso minha primeira tentativa foi moer o Aomori Microlot próximo do café mineiro, o que é bem fino. Escolhi a granuralidade inicial para espresso, que seria o primeiro nível que eu posso usar do meu Timemore sem estragá-lo. Isso demorou uma eternidade. Juro que pensei que tinha criado um vórtex no espaço-tempo e meu moedor começou a cuspir café ad infinito. Mas, enfim, uma hora acabou. Passei ambos no filtro de papel, cada um com metade do total.
O resultado ficou bom, mas o Aomori saiu meio apagado. Seu tom cítrico é bem forte e isso se manteve, mas todo o resto foi por conta do Tamandaré: amargor, corpo, notas mais achocolatadas... não, estou brincando. Um café já moído fino depois de cinco meses aberto só lembra café, mesmo.
Então fui buscar a versão 2 e a 3. Para a versão 2 insisti em moer o Aomori até o infinito e usei Aeropress com infusão. Porém, aumentei a dosagem do Aomori e diminuí do Tamandaré, o que gerou ainda um resultado bem encorpado, mas mais equilibrado.
Meu ponto forte foi a versão 3, onde eu entendi que ambos os cafés precisavam ser preparados separadamente, juntando-os no final. Então usei a mesma proporção anterior, mas a moagem do Aomori foi de coado. Ambos eu passei na Aeropress, mas em momentos distintos. Confesso que passei muito rápido o Tamandaré, pois estava com medo dele dominar novamente.
E o resultado foi muito bom! Faltou um pouco de corpo, mas o equilíbrio entre o amargor e o cítrico tornou a bebida leve, mas não simples demais. Acho que é isso que estava me incomodando no Aomori 100%: ele é bom, mas simples demais. Seu tom cítrico dominava. Com a presença do teor mineiro o jogo mudou. O café se assemelhou à minha memória afetiva do que é um café e ao mesmo tempo o tom cítrico refrescante colaborou para uma complexidade maior na bebida.
Esse experimento me convenceu que é gostoso experimentar blends de vez em quando. Uma bebida muito boa pode surpreender ainda mais se juntarmos o melhor dos mundos.
# Why I will also build my own shitty static site generator
Caloni, 2023-06-05 blogging projects [up] [copy]O texto Why I Built My Own Shitty Static Site Generator resume muito bem minhas restrições sobre Static Site Generators em geral e acaba devaneando por caminhos pelos quais eu também passeio quando penso em meus textos e as diversas formas dele se propagar. É um ensaio, quase rascunho, do seu autor, mas já abrange para mim de uma maneira holística o suficiente os dilemas entre usar o que já está pronto e perder a liberdade de colocar as ideias no papel ou preferir se fechar nas soluções caseiras, capengas, mas 100% autorais. Não chega a ser o texto que eu gostaria de ter escrito sobre o assunto e que não precisarei escrever por enquanto, mas é um começo corajoso. Os mesmos desafios estão aí.
Porque qual o motivo de eu depender de um formato se a forma não é o conteúdo?
# Asciidoc is the best
Caloni, 2023-06-05 essays english coding [up] [copy]After reading about the purpose and current implementation of asciidoctor I realize that asciidoc is the best text standard for the future of the blog. I say that based on the structure care of the format, the embebbed metadata into its own format and the clear objective of being a unique and formalized standard, what could simplify a lot the necessity of writers and publishers of keeping a text base as the original and yet keep the structure inside with almost no effort in the side of the writers.
Based also on the article Why I Built My Own Shitty Static Site Generator I also realized hugo is not the best tool to convert my texts to publish, despite being the best for so many years. I need to implement this tool, for my single oriented purpose. Being that, the use of Hugo will be temporarily.
So the TL;DR of all this is:
instead of using the yaml header (not sure how to keep the blog running in
this phase yet);
The next step after this PR is to develop a tool to replace hugo and automatize blog, ebooks and whatever the blog can be turned on (with any set of content).
The final solution for the blog is a single folder with a bunch of asciidoc files and its metadata. The publishing tool must be able to filter and generate related content based on metadata and parameters.
I expect to keep or reconstruct the text history based in this single folder, but I am not sure yet if it is worth it.
# O Quarto Verde (ou Ignorem meus textos fáceis)
Caloni, 2023-06-05 movies essays [up] [copy]Passei 10 anos escrevendo sobre filmes e não consegui refinar um formato. O motivo me veio aos poucos: não existe uma fórmula mágica para falar sobre qualquer coisa, inclusive filmes. E nem deveria.
One day in 1904 the young Franz Kafka wrote a letter to a friend defining the books that are worth reading. “I think we ought to read only the kind of books that wound us,” he wrote. “If the book we're reading doesn't wake us up with a blow to the head, what are we reading for? So that it will make us happy, as you write? Good Lord, we would be happy precisely if we had no books, and the kind of books that make us happy are the kind we could write ourselves if we had to. But we need books that affect us like a disaster, that grieve us deeply, like the death of someone we loved more than ourselves, like being banished into forests far from everyone, like a suicide. A book must be the axe for the frozen sea within us. That is my belief.
Não apenas livros. Pensamentos que valem a pena não podem ser fáceis. Se for, é um passatempo esquecível e deve ser ignorado. Então, por favor, ignorem meus textos mais brandos.
É o filme do Truffaut que eu acabei de assistir. Algo sobre a chama verde. O diretor francês amiguinho do Godard adorava uma auto-flagelação e coitadismo reflexivo. Este é mais um desses. O protagonista vive o pós-guerra como se já estivesse morto, pois nutre amor apenas pelos que já se foram, incluindo sua mulher um ano após noivarem. O filme é bom pelas tecnicidades e porque ele não se apega aos cacoetes do diretor, mas não sobrevive à pieguice em alguns momentos. Principalmente o final.
Em tempo: descobri olhando o IMDB que o diretor faz uma ponta como protagonista. Não que isso interesse.
Eu havia guardado mentalmente mais alguns temas para abrir um poste de devaneios, mas isso faz alguns dias e acabei com mais coisas na cabeça do que sou capaz de guardar para blogar. O bom de viver é que é um processo de retroalimentação de blogues. Em breve terei mais conteúdo. Só é preciso escrever. O formato é detalhe.
# Reviravolta mantendo a tensão
Caloni, 2023-06-05 chess [up] [copy]1. e4 e5 2. Nf3 Nc6 3. d4 exd4 4. Bc4 Bc5 5. c3 dxc3 6. Bxf7+ Kxf7 7. Qd5+ Ke8 8. Qxc5 Nf6 9. Nxc3 d6 10. Qg5 Qe7 11. O-O Be6 12. Re1 Kd7 13. Nd5 Nxd5 14. Qd2 Nf6 15. e5 Nd5 16. Nd4 Nxd4 17. Qxd4 dxe5 18. Rxe5 c6 19. Bg5 Qd6 20. Bf4 Nxf4 21. Qxf4 Kc7 22. Rae1 Rhf8 23. Qg5 Rae8 24. Qxg7+ Kb8 25. Qg3 Kc7 26. Qg7+ Rf7 27. Qg3 Bxa2 28. Rxe8 Bc4 29. R8e3 Qxg3 30. hxg3 Rd7 31. Re7 Rxe7 32. Rxe7+ Kd6 33. Rxh7 Kc5 34. Rxb7 a5 35. Ra7 Kb4 36. f4 a4 37. f5 Kb3 38. Rb7+ Ka2 39. Rb6 c5 40. f6 Ka1 41. Kf2 Ka2 42. g4 a3 43. bxa3 Kxa3 44. g5 Ka4 45. g6 Ka5 46. Rb8 Ba6 47. f7 Bb7 48. Rxb7 c4 49. f8=Q c3 50. Qa3# 1-0
# Vilarejo do Amor
Caloni, 2023-06-05 series [up] [copy]Depois da carência que foi perder Terrace House durante a pandemia e com o suicídio de uma das participantes, este reality japonês abandona o glamour de colocar jovens bonitos com profissões moderninhas em uma casa estilosa e coloca quarentões isolados em uma casa clássica japonesa no meio do nada. E precisando de reformas. O objetivo? Eles encontrarem seu último, definitivo amor. Ousado? Sim. Tradicional? Graças a Deus.
O principal nesta fórmula do amor deste novo programa é que o participante que quiser arriscar em um romance deve sair da casa. Ele irá tocar um sino e confessar na presença de todos da casa seu amor. A pessoa escolhida deverá responder no dia seguinte se sairá da casa junto. Não há segunda chance para quem toca o sino.
Com dois comentaristas que nos fazem ter saudades dos de Terrace House porque eram muito melhores, Vilarejo do Amor possui um arco dramático dos mais inusitados. Nos faz pensar se essa história se desenvolveu naturalmente ou foi tudo planejado. É quando a paixão da vida real pode ou não estar em um roteiro. O que torna o programa bom é que isso acaba não importando tanto.
Segue aqui uma pequena nota de arrependimento por não saber da existência deste saite até o Fernando Mercês do Mente Binária me informar. A Vovó Vick era uma médica formada e começou a se interessar por computação e nunca mais parou. Ela publicou um livro sobre criptografia. Ela escreveu artigos e mais artigos sobre programação, sistema operacional, linguagem assembly e muito mais. Ela viveu o boom dos PCs como nós, jovens, mas ela já estava na terceira idade, o que se tornou um mero detalhe e curiosidade, já que o conteúdo de seu saite dá de dez a zero em muitos jovens apenas curiosos com a área ou querendo ganhar dinheiro. A Vovó mergulhou fundo na tecnologia. E é muito bom apenas saber disso. Uma pena não conhecê-la a tempo. Que faça boa viagem. E que nos encontremos em outras configurações da matéria e da energia.
# El Porvenir: Laborum Malbec 2020
Caloni, 2023-06-06 wine [up] [copy]Essa garrafa que já acabou foi um Malbec 2020. Nuevos Suelos a subcategoria, mas ainda da série Laborum. As uvas vieram da Finca Alto Rio Seco, onde 70% do terreno é de rochas com sedimentação calcária. São produzidas 7000 garrafas. Não há passagem por barrica porque o objetivo deste rótulo é levar ao consumidor o que veio do solo de forma autêntica. Geralmente o apreciador esnobe de vinhos diria que esta decisão tira a complexidade da bebida, mas nesse caso posso dizer que nem um pouco. A tara por passagem em barrica serve para muitas colheitas, mas essa pode ficar do jeito que está.
# El Porvenir: Laborum Tannat 2019
Caloni, 2023-06-06 wine [up] [copy]É revoltante o quão bom são os vinhos da El Porvenir. A agressividade dos taninos que lembram as uvas regadas a conta-gotas no meio de um deserto árido, arenoso e praticamente infértil se traduz em uma taça sempre memorável, e que de brinde remete a memórias da própria vinícola. A garrafa que bebo agora é um Tannat de 2019, ou seja, não traumatizado pela pandemia. A Finca é a El Retiro, a mais antiga da vinícola, plantada em 1945. Se trata de um terreno arenoso com poucas rochas. Pela idade das parreiras elas foram plantadas no esquema pérgola. Ele é ríspido, mas ainda frutado. O tanino raspa na boca e a envolve em um abraço que acolhe o paladar. Há tons vegetais e minerais na mesma taça. O teor alcoólico ainda é forte, mas faz parte da experiência completa.
Uhu! Estou de volta para as baixarias =). Irei trabalhar com engenharia reversa, serviços e drivers no Windows, talvez algumas telas azuis da morte e alguns travamentos inexplicáveis. Ou seja, só diversão.
E vou aproveitar meu processo de onboarding para recomendar as ferramentas que já utilizo no meu dia-a-dia e as novas que meus colegas me passaram.
No Visual Studio já vem o SDK de desenvolvimento para Windows. E dentro dele vem as libs e headers para você conseguir compilar programas em C e C++ que usam a API do Windows.
Porém, o importante de lá é que existem ferramentas para realizar análise de executáveis, como o DumpBin, e debug remoto através de uma porta TCP; na seção de VMs falo sobre isso.
O WDK é o SDK para kernel mode. Lá haverá libs e headers também, mas mais focadas para o desenvolvimento de drivers. E uma ferramenta, ou melhor dizendo, um conjunto de ferramentas que não pode faltar e que está lá é o...
Sem WinDbg a vida fica um pouco mais triste. Dentro do pacote Debugging Tools há ele e suas variantes, como o kd, ntsd e cdb. Também há o gflags, para setar várias flags importantíssimas na depuração do sistema operacional, e uma documentação bem extensa para desenvolver scripts e extensões para depuração, além de outras coisas mais, como um servidor de símbolos.
Não conhecia este depurador. Ele é fonte aberto, o que já é interessante. Baixei e pretendo olhar mais de perto. Jurava que iriam me sugerir o OllyDbg pelo livro que estou lendo de reversa. Este carinha deve ter sido lançado após o livro.
Uma ferramenta de análise de PE, ou Portable Executable, o formato dos EXEs e DLLs do Windows. Eu particularmente uso o DumpBin, mas vou dar uma olhada nesta recomendação que deve agilizar um pouco as análises.
Usava esse carinha há muitíssimo tempo atrás, para uma tarefa não-nobre: editar na mão os resources pós-compilados do C++ Builder porque ele vivia cheio de bugs. Ah, e também manipular chaves criptográficas guardadas nos resources. Ele também é bem legal para achar novos ícones e incrementar seu computador, além de um ótimo editor de strings.
Eu já tentei usar o Vim no modo de comparação, mas WinMerge para Windows não se compara. Ele é simples e eficiente. Mantenho apenas o executável no meu cinto de utilidades e ele consegue se virar para pastas inteiras. Suas configurações permitem ignorar detalhes como final de linha e indentação.
Um editor hexa que virou queridinho depois que um colega da Open me apresentou. Ele é daqueles um executável apenas que faz todo o serviço de mostrar dados em hexadecimal de qualquer arquivo ou mesmo da memória (ou do disco).
Não vou perder tempo descrevendo cada uma das fantásticas ferramentas da SysInternals, então tomaí: um toolkit cheio delas.
Não conhecia este aqui e fiquei muito empolgado. Ele faz comparação entre registros! Imagina a maravilha que isso será para alguns de meus projetos que envolvem diretivas de acesso...
Essencial para analisar tráfego de rede no detalhe, já me quebrou muitos galhos quando precisava entender erros de comunicação com a bolsa de valores. Sim, eles também erram. Quem diria.
Este é um scanner de memória feito para aplicar patches em jogos. Que feio! Porém, para um reverseiro pode ser útil para encontrar padrões e reconhecer comportamento.
Guidra é uma suite de ferramentas de engenharia reversa desenvolvida pela NSA (agência americana de segurança). Ele é fonte aberto e permite desenvolver programas acessórios para análise dos programas incluídos em um projeto. No entanto, com o que já está disponível é possível escarafunchar o Portable Executable, diversas estruturas de dados e um decompilador simples e intuitivo de se mexer.
IDA é um disassembler que brilha na análise estática. Ele ajuda muito a reconstruir código-fonte ou entender comportamento de funções inteiras apenas lendo o assembly e os nomes sugestivos dos calls e jumps que a ferramenta lhe fornece.
Para quem faz reversa de componentes COM ou WinRT e até UWP apps essa ferramenta vai ser muito útil. Ela lista as classes, interfaces e tipos registrados na máquina.
Esta é uma ferramenta para gerar screenshots e vídeos, ou seja, gerar evidência. Qualquer uma na verdade serve, mas essa foi a sugestão do colega e pretendo guardar aqui.
Virtualizar o Windows é essencial para instalar drivers instáveis, analisar telas azuis e o comportamento do sistema como um todo, do user mode ao kernel. Portanto, trate de arrumar algumas das soluções disponíveis. Eu uso VMWare desde que foi lançada e já comprei algumas licenças de novas versões dos caras, porque eles são foda. Você pode usar também VirtualBox ou outras por aí. O importante é virtualizar.
Por falar nisso, é importante lembrar que o Windows 11 requer um chip de TPM 2.0 disponível para ser instalado, e por isso você irá precisar do VMWare 17 ou superior. Se atente a este guia de instalação para conseguir rodar o Win11 virtualizado.
A depuração remota é importantíssima quando se precisa acessar múltiplos ambientes, muitos deles montados de uma maneira bem específica para reproduzir um bug. Por isso o uso do msvsmon, disponível na instalação do Visual Studio, é primordial.
Você pode encontrar as versões para x86 e x64 do msvsmon dentro da pasta de instalação do Visual Studio. Por exemplo:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\Remote Debugger
Para instalar na máquina guest tudo que você precisa é copiar essas pastas e rodar qualquer um dos msvsmon.exe disponíveis. Rode pelo menos uma vez para acertar a porta no Firewall do Windows. Depois disso pode rodar como tarefa automática.
Eu acho muito útil configurar um serviço que rode o msvsmon, de forma que mesmo antes de logar já é possível depurar programas. Para isso eu uso uma outra ferramenta fantástica, o NSSM, mas qualquer outra ferramenta que transforme um programa em serviço já serve.
Usando o NSSM configure o programa Msvsmon para rodar como um serviço. Aqui está uma configuração bem direta, sem autenticação, para usar o msvsmon através do nssm:
nssm.exe install msvsmon c:\tools\rmdbg\x86\msvsmon.exe /anyuser /noauth /timeout 9999999 /silent
Use o path completo de onde está o msvsmon.exe na máquina guest para rodar este comando. O serviço é instalado por padrão como automático, então ao reiniciar a máquina ele já estará em execução.
Qual a graça de depurar apenas os programas em user mode? E aquela tela azul marota, ou acompanhar o boot da máquina em câmera hiperlenta? Aproveite que já está com sua VM bonitinha no ar e configure o debug de kernel rodando um cmd como administrador e executando alguns comandos no bcdedit.
bcdedit /copy {current} /d Debug bcdedit /debug {new-id} ON bcdedit /dbgsettings SERIAL DEBUGPORT:1 BAUDRATE:115200
Isso irá criar uma segunda opção de boot que irá aparecer quando ligar a máquina (timeout padrão de 30 segundos para escolher). Se configurar debug pela porta serial crie uma na máquina virtual apontando para um named pipe. No WinDbg conecte usando este pipe (e.g. `\\.\pipe\com_1´).
Agora começa a diversão =).
# Usando Awk para gerar sites e medidas de performance
Caloni, 2023-06-15 coding [up] [copy]Hoje achei um projeto muito genial e óbvio chamado Zodiac, que é um static site generator escrito em awk. Mas claro! Gerar sites estaticamente é sobre manipular texto de entrada para texto de saída. Como não pensei nisso antes?
Baixei o projeto e comecei a fazer alguns testes de performance. Porém, como ele depende de bash tive que rodar em um WSL (Debian) e o I/O não ficou dos mais rápidos. Estava demorando quase um arquivo por segundo. Isso para meus mais de 4k arquivos iria demorar uma eternidade.
Aproveitei o embalo e criei um projeto bem básico em C++ que apenas abre um arquivo, lê o conteúdo e escreve em outro arquivo (o baseline). Ele demorou 12 segundos no máximo para operar em todos os posts. Bom, mas poderia ser melhor.
#include <string> #include <iostream> #include <fstream> #include <sstream> #include <filesystem> using namespace std; namespace fs = std::filesystem; std::string ReadEntireFile(std::ifstream& in) { std::ostringstream sstr; sstr << in.rdbuf(); return sstr.str(); } int main() { std::string path = "."; for (const auto& entry : fs::directory_iterator(path)) { string path = entry.path().string(); ifstream ifs(path); ofstream ofs(path + ".html"); if( ifs && ofs ) { string content = ReadEntireFile(ifs); ofs << content; } } }
Fiz um teste usando o próprio awk, mas ainda não sei como fazer para manipular vários arquivos de uma vez e acabei criando uma batch, que acho que deixou a execução desnecessariamente lenta. Volto para isso depois.
@echo off awk -f markdown.awk post.md > post.html rem 4K lines
Por fim, apenas para comparação com a API nativa, executei um comando copy que apenas copia todos os arquivos para uma nova pasta. O resultado: 6 segundos. Mas OK, é apenas uma cópia de apontamento no file system. O comando nem precisaria abrir para leitura. Acho que devo ficar com os 12 segundos como baseline, mesmo, ou cerca de 300 arquivos por segundo.
mkdir copia copy *.md copia > NUL
# Critical Sections and Outlook
Caloni, 2023-06-15 coding debugging english reversing [up] [copy]Today was a happy crush analysis day, because I receive an Outlook memory dump the moment it frooze the main window in the beginning of the process. I asked for one because it could be useful to another analysis I was doing with Office server communication.
I discovered that the main window thread was waiting for a critical section used by a part of the Office code called `OsfIdentityManager` when calling the function `EnsureInit`. The code responsible for acquire the lock is associated with the name `OsfLock`. The same cs was trying to be acquired by another thread. Looking at another similar threads it seems a group of worker threads starting at the entry `mso20win32client!CIOPort::ThreadProc`. Bellow is the result of the `!cs` command in WinDbg:
DebugInfo = 0x00000195b9ce4f00 Critical section = 0x0000019581b2d590 (+0x19581B2D590) LOCKED LockCount = 0x2 WaiterWoken = No OwningThread = 0x0000000000018e9c RecursionCount = 0x1 LockSemaphore = 0xFFFFFFFF SpinCount = 0x00000000020007d0
The moment the dump was generated the thread that had acquired this cs was inside the same function `OsfIdentityManager::EnsureInit` and several frames above was calling the native API `ntdll!NtQueryFullAttributesFile`, when I discovered that this application is using Microsoft Application Virtualization based on the hook it was installed:
. 58 Id: 661c.18e9c Suspend: -1 Teb: 0000003c`34078000 Unfrozen Start: mso20win32client!CIOPort::ThreadProc (00007ff8`70ba3ef0) Priority: 0 Priority class: 32 Affinity: fffff # Child-SP RetAddr Call Site 00 0000003c`382fedc8 00007ff9`089c52a8 ntdll!NtQueryFullAttributesFile+0x14 01 0000003c`382fedd0 00007ff9`089b9483 AppVIsvSubsystems64!vfs_query_full_attributes_request::pass_through+0x28 02 0000003c`382fee00 00007ff9`089b384b AppVIsvSubsystems64!AppV::VFS::Filesys::virtualize_nt_query_full_attributes+0xc3 03 0000003c`382ff050 00007ff9`089b61fe AppVIsvSubsystems64!vfs_hooks::NtQueryFullAttributesFile+0xeb 04 0000003c`382ff100 00007ff9`7774849f AppVIsvSubsystems64!vfs_hooks::hooked_NtQueryFullAttributesFile+0x2e 05 0000003c`382ff130 00007ff8`70b957c0 KERNELBASE!GetFileAttributesExW+0x9f 06 0000003c`382ff230 00007ff8`70b95779 mso20win32client!MsoGetFileAttributesW+0x20 ...
Virtual applications are installed on centrally managed servers and delivered to users as a service in real time and on an as-needed basis. Users launch virtual applications from familiar access points and interact with them as if they were installed locally.
Considering that that is the thread that is locking the cs that is freezing other two threads, including the main window thread, I believe that somehow there is a connection with the delivery service from the App-V with the Outlook slowliness when opening or perhaps in other moments where a unavailable module is requested. Results from the web have the usual troubleshooting sugestions as restore Office installation, run in safe mode and disable AppData network redirection, but I am not sure if this is the case.
Two main commands used in WinDbg for the analysis was `!uniqstack` to show the... unique stacks in the process, and `!cs`, to show all critical sections and its states.
[Microsoft Application Virtualization : App-V
# Cuidado de ambos e a gafe no final com a dama
Caloni, 2023-06-15 chess [up] [copy]Esta partida estava sendo bem jogada por ambos os lados. Estava difícil de progredir, pois não havia muitas ideias. Estava lento. Até que minha ideia de pesar na coluna do bispo ao mesmo tempo que atacava a dama fez meu adversário pensar demais, acredito eu, pois ele estava ameaçando o peão da torre com o bispo dele. Tanto pensou que pendurou a dama. Uma pena. Estava equilibrado (acredito).
1. e4 c5 2. Bc4 Nc6 3. Nf3 e6 4. Nc3 d6 5. O-O Nf6 6. Re1 h6 7. h3 Be7 8. d4 cxd4 9. Nxd4 O-O 10. Nf3 e5 11. Nd5 Nxd5 12. Bxd5 Be6 13. a3 Qc7 14. Nh2 Rac8 15. Re3 Bxd5 16. Qxd5 Kh8 17. Rg3 Bf6 18. Be3 Ne7 19. Bxa7 Nxd5 0-1
# Debugging a non signed driver in Windows 10
Caloni, 2023-06-15 coding debugging english [up] [copy]Not always just to disable driver signing enforcement work in Windows. In Windows 10 when tried to start a driver after reboot with `bcdedit -set TESTSIGNING ON` I still got the `StartService FAILED 577: Windows cannot verify the digital signature for this file` message.
In order to start a driver non signed by Microsoft you still need some signature in the binary.
rem create the certificate makecert -r -pe -ss PrivateCertStore -n CN=My.com(Test) -eku 1.3.6.1.5.5.7.3.3 MyTest.cer rem install the certificate (run as admin) certmgr /add MyTest.cer /s /r localMachine root rem sign the driver signtool sign /v /fd sha256 /s PrivateCertStore /n My.com(Test) /t http://timestamp.digicert.com MyDriver.sys
# Gran Enemigo 2017
Caloni, 2023-06-15 wine [up] [copy]A linha El Enemigo contém uma qualidade e equilíbrio ímpares. Meu amigo abriu uma dessas garrafas quando o visitamos. Se trata de um blend de Malbec e Cabernet bem equilibrado, praticamente não-alcoólico. Apesar de não ser um Cabernet simples de beber ele deve ter aliviado o peso do Malbec e deixado o resultado final mais suave, apesar de com bom corpo. Os taninos não dominam a bebida. É bom constatar que taninos não são mais os protagonistas isolados das bebidas mais estilosas e caras de Mendoza. Há espaço para todos os sabores.
# Ikkousha Tonkotsu Ramen
Caloni, 2023-06-15 food [up] [copy]Não seria justo fazer um review do delicioso Tonkotsu pedindo delivery. Portanto, aguardei nossa primeira visita pós-pandemia direto ao local para sentir as impressões de um dos melhores lámens da cidade. E ele continua um dos melhores, junto ao Aska. Ambos estão no topo, e por serem diferentes, não competem. O caldo de mocotó japonês que o Ikkousha serve é único, denso, complexo e delicioso. É compactado, também. Mesmo tomando um mini minha impressão é que o estômago vai explodir depois das primeiras colheradas. É uma ótima pedida para uma noite fria. A cozinha é eficiente e habilidosa. Na noite de terça-feira que fomos, por volta das 20 horas, havia uma boa fila na entrada e poucos atendentes que fazem o que dá, mas a gerência precisa urgente colocar mais gente, pois mesmo sendo o espaço sendo pequeno há horários de pico. Esqueceram da gente por um tempo, mas graças a um dos cozinheiros fomos lembrados. O lámen deles ao vivo é muitíssimo melhor que o delivery. Há também outras versões, como o apimentado god fire ou a mistureba de sabores do EAK, com a sensação predominante de frango.
# O Poço
Caloni, 2023-06-15 movies [up] [copy]Este filme é muito louco. Ele é assistível do começo ao fim, mas continua sendo uma merda. Sua tentativa de inputar uma mensagem filosófica, social ou alguma bobagem do tipo passa por cima da narrativa e de repente desce de uma mesa elevador de um restaurante muito estranho uma maluca buscando o filho e sendo estuprada andar por andar. O herói do filme sonha que transou com ela. O velho do filme ajuda o espectador a entender as regras do jogo antes que criemos uma saída para aquele pesadelo sobre uma das necessidades mais básicas do ser humano: a fome.
Isso me lembra um senhor com quem conversei e que irei manter em anonimato sem dar maiores detalhes. Ele contava vários causos da vida e dava sua, vamos acreditar, opinião. Uma delas é que os entregadores de comida em São Paulo estavam morrendo de fome. Ele disse para a filha, que mora em São Paulo e que pediu um iFood: "filha, faça um sanduíche de mortadela para o infeliz e dê para ele". Então a filha dele deu (o sanduíche). A filha deve se chamar Nina ou algo do tipo, irmã do Lucas. Aconteceu de verdade. Motoristas de iFood entregando comida a noite inteira e indo dormir com fome. E a heroína dessa história em vez de dar parte de sua pomposa refeição de classe média entrega um sanduíche de mortadela para o infeliz e atônito motoqueiro.
Este causo contém mais insights sobre a sociedade em que vivemos do que este filme falado em espanhol. Porém, quando o filme acabou me deu uma fome gostosa.
# Pizzaria do Eataly
Caloni, 2023-06-15 food [up] [copy]Íamos em outro restaurante essa noite, mas ele não estava aberto. Então lembramos que há muito tempo atrás fomos em uma pizzaria no Eataly com um casal de amigos e a comida estava até que boa. Bom, não foi dessa vez. Durante esse tempo eu aprendi a cozinhar massas e a fazer muita própria massa de pizza em casa assistindo canais no YouTube. Posso dizer que mesmo sem muita prática a minha massa é muito mais leve do que da pizzaria de cima. Ela é bem assada, mas sua borda é extremamente massuda. Onde deveria haver apenas ar há um monte de massa. O recheio também não teve nada demais, pedimos uma calabresa e uma com um queijo e molho. A de queijo estava OK, mas a de calabresa já provamos uma melhor perto de casa, pizzaria de Heliópolis, baratinha e bem feita. Ah, sim, tem esse detalhe: os produtos no Eataly são absurdamente caros, tanto por causa da região onde ele fica quanto o público que o frequenta; fora você não sente que o preço é justo. É apenas inflado. Por fim, o atendimento é nível paulistano padrão. Os atendentes distraídos e correndo entre as mesas. É quase um fast food, com a única diferença que levam os pratos para você. A gorjeta também não é nada justa: 15% por esse serviço. Eu preferiria ter dado esse valor para o entregador de pizza e ter comido a pizza baratinha aqui perto de casa. Ou ter feito a própria.
# Pulenta Malbec Gualtallary 2016
Caloni, 2023-06-15 wine [up] [copy]Um Malbec de Mendoza de respeito. Reservado para uma reunião muito especial de amigos, este vinho não é barato, mas entrega uma garrafa da série de alturas da Pulenta. Há várias alturas disponíveis no Valle de Uco, e esta é de 1300 metros de altitude, em vinhas plantadas em solos rasos e pedregosos, cheio de cálcio. As uvas são regadas por gotejamento da água de degelo da cordilheira. O sabor é vibrante, equilibrado, mas nem tanto. Há personalidade, corpo, taninos e Malbec. Ah, Malbec...
Existe uma cafeteria pequena no mercado municipal de Poços de Caldas localizada na parte de cima. Dentro há cafezes especiais que são torrados lá mesmo no mercado. Pedi um espresso e gostei muito; equilibrado sem amargor. Acabei levando para meu amigo que iria visitar em seguida a versão mais popular, de rapadura, e levei para casa a versão doce de leite. O aroma desse café depois de moído é sensacional. Porém, na hora de beber ele é bem mais leve, com pouco corpo e lembra apenas vagamente doce de leite (os aromas de café costumam enganar).
Conversando com o barista conheci também uma versão de torra clara que não sabia da existência e que de acordo com ele é muito popular entre os europeus que passam por lá. Lendo um pouco sobre níveis de torra percebi que o que ele quis dizer é que os gringos vão até lá para experimentar o café no nível Cinnamon (ele disse um outro nome que não encontrei na web) para experimentação profissional. Este nível de torra fica bem no início dos estalos da torra, onde o próximo nível, City Roast ou Light Roast, seria o final dos estalos e a prova feita com muito pouco do que foi acrescido pela torra; fica mais do café, mesmo.
Eu experimentei esta torra em casa extremamente clara porque ele me deu uma prova de 20g. Foi bem difícil moer no Timemore, o que seria ainda mais difícil no Hario. Os grãos ficaram emperrando por quase todo o processo (moagem para Aeropress). A cor dele é de paçoca e minha memória ficava tentando me dizer que estava também cheirando a paçoca. A cor final dele é de caramelo, não é de café, e o sabor lembra grama e vegetais em geral. Há um nível perceptível de doçura, provavelmente proveniente da fruta do café, e zero de amargor. Não se assemelha em nada ao café tradicional que é passado, mas pode ser interessante para os fãs dessa moda de grãos fermentados e notas mais diferentonas. Lembrando que nesse caso o resultado também possui zero acidez.
Agora voltando para o doce de leite. Até então não sabia se conseguiria transferir esse aroma maravilhoso de doce de leite enquanto moía os grãos para a bebida final. Várias passadas na Aeropress e no coador de pano deram um resultado aquém do que eu esperava. Até que hoje eu passei no Melitta e ele veio! Exatamente o aroma que eu sinto quando os grãos viram pó eu consegui sentir no resultado de 18g para 240ml de água em três passadas. Agora posso sentir se tratar de um café delicado, mas que ao mesmo tempo contém uma textura perene. O doce sobressai à acidez. Não existe amargor presente.
This is the VPN solution used in the project I am working on, a simple and secure packet distribution and controlled by the IP addresses configured for each peer. There is a very nice example in the home of WireGuard project.
In other words, when sending packets, the list of allowed IPs behaves as a sort of routing table, and when receiving packets, the list of allowed IPs behaves as a sort of access control list.
This is what we call a Cryptokey Routing Table: the simple association of public keys and allowed IPs.
# Joan is Awful (Black Mirror)
Caloni, 2023-06-17 series [up] [copy]Temporada nova de Black Mirror estreou com tudo neste episódio que lembra os trabalhos mais inspirados do roteirista Charlie Kaufman (não é ele), mas nem por isso pode ser chamado de plágio.
Mas sua ideia está longe de ser original. Na verdade está na boca de todo mundo que critica Netflix. Eu mesmo já imaginei um futuro da gigante de streaming nesses moldes.
Porém, o episódio vai além da paranóia da irrelevância dos indivíduos e constrói uma história tensa, instigante, que se desdobra aos poucos e nos deixa presos sem tirar os olhos da tela. Irônico, se considerarmos que em dado momento a CEO da flix alternativa revela que os testes com produções mais otimistas não tinham tanto engajamento quanto gerar medo nos espectadores, o que acaba sendo uma discussão mais profunda sobre a escolha do gênero instigante se pararmos para pensar.
A Bublefix também é péssima quando se trata de episódios de Netflix, e isso infelizmente é ótimo, pois apenas enxergando o pior em nós mesmos podemos pensar em sermos versões melhores amanhã. Porém, provavelmente ninguém entendeu este episódio (como a busca do Google revela, vários posts "explicando" a reviravolta final) e ninguém vai usar a série como um espelho que mostra o que há de pior em nós mesmos.
Comecei apontando minhas peças para cima do rei adversário. Minha dama estava deveras avançada, mas ameaçava o mate com o bispo branco. No entanto, eu adversário fez a mesma coisa. Então sem pensar em toda a combinação imaginei ficar melhor trocando minha dama pelas duas torres e fazer algo com o ataque descoberto do bispo branco ao rei adversário. Só não sabia que seria mate. No final ficou parecendo uma combinação que eu pensei antes.
1. e4 e6 2. d4 d5 3. Nc3 Nf6 4. f3 dxe4 5. Nxe4 b6 6. Bd3 Bb7 7. Bg5 Be7 8. Bxf6 Bxf6 9. Ne2 Nd7 10. O-O O-O 11. Kh1 Be7 12. c3 Nf6 13. N2g3 Nd5 14. Qd2 Nf6 15. Rae1 Re8 16. Ng5 h6 17. N5e4 Nxe4 18. fxe4 Bh4 19. Qf4 Bg5 20. Qxf7+ Kh8 21. e5 Qd5 22. Ne4 Rf8 23. Qxf8+ Rxf8 24. Rxf8+ Kh7 25. Nf6# 1-0
# Pão de queijo a frio com fubá de canjica
Caloni, 2023-06-17 cooking [up] [copy]Hoje experimentei uma receita que mistura os ingredientes do pão de queijo que já conhecemos e coloca um terço do polvilho de fubá de canjica, uma moagem bem fina de canjica usada para outras receitas como broinha. O pão não cresce tanto, acho que devido à falta de escaldar o polvilho com os líquidos fervendo. Porém, é uma receita rápida e que funciona: é só misturar os ingredientes e fazer as bolinhas.
# Na sua bunda, Platão?
Caloni, 2023-06-25 cooking coffee [up] [copy]Esta rápida e curiosa epopeia brinca com a teoria das ideias do filósofo grego da Antiguidade Platão. É uma tentativa bem-humorada (ou não) de tentar colocar os pingos nos is de quem ainda está embasbacado com a experiência de degustação de café especial e torra própria que se segue. Os cafés citados são do Sítio Posses e do Rancho São Benedito, adquiridos pelo serviço de microtorrefação de Pereira Villela (ótimo, por sinal). O grão verde é aleatório de mercado municipal.
Torrei um café verde comprado em Poços. Peguei 50g dos grãos e deixei em fogo baixo dentro de uma panela, mexendo sem parar com uma colher de pau. Meu objetivo era chegar no nível de torra logo depois do primeiro estalo, quando o grão torna-se bebível. Fiz isso. Abaixei a temperatura em uma forma que dissipa rapidamente o calor. Deixei descansando e passei um café depois de algumas horas. Não houve sabor de gás carbônico e acredito que é por causa da torra bem clara. O sabor é bem adstringente, mas bebível. Lá no fundo é possível sentir um pouco da fruta, mas bem pouco e depois de quase terminar. Não há quase nada de complexidade em um café desses, mas há uma lição: como se parece um café bem simples, com grãos defeituosos, e sem a torra escura para disfarçar? Se parece com isso: uma bebida quase sem graça, mas com algumas sutilezas, imaginárias ou não.
No mesmo dia chegou mais tarde os dois cafés que havia pedido, vindos de Itajubá pelo Pereira Villela. Pedi dois pacotes de grãos de 250g do Rancho São Benedito e do Sítio Posses. Um foi torrado ontem mesmo e o outro na antevéspera. Passei os dois ao mesmo tempo. Ao abrir as embalagens o aroma foi praticamente idêntico e eu identifiquei o gás carbônico ainda presente. Identifiquei justamente porque eu já fiz torras mais escuras em casa e é esse o aroma. Um pouco desagradável.
Deixei ambos em infusão de pelo menos 3 minutos com uma moagem para coados, mas passei na Aeropress em filtro de metal para sentir a textura e não deixar a pressão exercer muita influência ainda. No copo os cafés diferiram. Um deles possui mais acidez. Depois de alguns goles dá para sentir um certo tom cítrico que me fez lembrar daquele café especial do The Coffee, ainda que em proporções bem menores. O outro possui um doce mais pronunciado e um sabor bem característico que pode fazer lembrar uva ou talvez jabuticaba. Ele também é ácido, mas um ácido diferente, acho eu.
Eu não sei qual é qual. Já me confundi. É proposital. Não fiquei marcando ou memorizando qual copo era qual porque eu queria entender se havia algo de diferente mesmo. E por isso nem me lembrei de ver as notas sugeridas no rótulo do produto. Verei agora. Um momento.
Antes, sobre a tonalidade. Apesar da torra ser bem próxima, algo em torno da média, um dos copos ficou levemente mais escuro que o outro. O menos ácido ficou mais escuro. O que faz sentido.
Agora voltando para as notas:
Eu chutaria que o primeiro café que provei foi o São Benedito e o segundo Posses. Por quê? Bom, não sei. O meu chute é baseado apenas nesse sabor característico do segundo, que lembra fruta, ainda que não fosse a que eu pensei. Se está "frutas vermelhas" em um e não há menção de fruta em outro sou inclinado a fazer este chute educado.
No entanto, reavaliando mais uma vez, o mascavo e caramelo possuem esse tom um pouco enjoativo do segundo. É algo que puxa para a rapadura. Está vendo a imaginação trabalhando? Já o primeiro não tem essa característica, mas pode ser confundido com algo frutado. Sua acidez que lembra sutilmente o The Coffee pode ser indício dessas "frutas vermelhas" na marcação.
Com isso encerro esta experiência. A ideia era entender o que nos leva a classificar um café de um jeito e o outro do outro. Porém, mais do que isso. É entender que para classificar precisamos de referência. Sem referência as impressões são vagas, como acidez e doçura. Que foi exatamente o que eu fiz antes de ir conferir as notas.
Agora que estou terminando os copos e já dei uma espiada nas referências as notas estão mais nítidas. Interessante como o cérebro humano trabalha com padrões ligados a referências. Sem isso o mundo todo é apenas um quadro branco. Onde estão as primitivas do mundo das ideias, Platão? Na sua bunda, por acaso?
# Reversing: Secrets of Reverse Engineering
Caloni, 2023-06-25 books reversing [up] [copy]Publicado pela Wiley em 2005, bem na época que comecei a me enveredar no trabalho com análise de trojans e técnicas antidebugging, o livro de Eldad Eilam veio bem a calhar na época e agora virá bem a calhar novamente, pois irei voltar a trabalhar na área. Naquela época começavam a surgir os ataques aos bancos online no Brasil e existia até um tookit que espalhava uma técnica ou duas entre os laranjas que queriam tirar uma casquinha da nova onda. O livro de Eilam busca juntar cada aspecto da engenharia reversa em um apanhado que irá nos dar insights e modus operandi de como proceder para cada tipo de desafio.
Parei a leitura na parte que começam os disassemblies para prática. É divertido, mas exige um tempo considerável para acompanhar. E neste primeiro mês no trabalho novo descobri que consigo me virar com os skills que já possuo, podendo deixar este prazer para mais tarde. É sempre bom poder afiar suas ferramentas, mas é preciso priorizar o que é mais importante para o dia-a-dia no momento.
Reverse engineering has been with us a long time. The conceptual Reversing process occurs every time someone looks at someone else's code. But, it also occurs when a developer looks at his or her own code several days after it was written. Reverse engineering is a discovery process. When we take a fresh look at code, whether developed by ourselves or others, we examine and we learn and we see things we may not expect.
In the early 1980s, IBM decided that it would no longer release to its customers the source code for its mainframe computer operating systems. Mainframe customers had always relied on the source code for reference in problem solving and to tailor, modify, and extend the IBM operating system products. I still have my button from the IBM user group Share that reads: "If SOURCE is outlawed, only outlaws will have SOURCE," a word play on a famous argument by opponents of gun-control laws.
Reverse engineering is a process where an engineered artifact (such as a car, a jet engine, or a software program) is deconstructed in a way that reveals its innermost details, such as its design and architecture. This is similar to scientific research that studies natural phenomena, with the difference that no one commonly refers to scientific research as reverse engineering, simply because no one knows for sure whether or not nature was ever engineered.
Which bring us to the most basic point to remember about assembly language: it is a class of languages, not one language. Every computer platform has its own assembly language that is usually quite different from all the rest.
Code-level reversing is really an art form. Extracting design concepts and algorithms from a program binary is a complex process that requires a mastery of reversing techniques along with a solid understanding of software development, the CPU, and the operating system. Software can be highly complex, and even those with access to a program's well-written and well properly-documented source code are often amazed at how difficult it can be to comprehend. Deciphering the sequences of low-level instructions that make up a program is usually no mean feat.
The primary claim made by Sega was that copies made by Accolade during the reverse-engineering process (known as “intermediate copying”) violated copyright laws. The court eventually ruled in Accolade's favor because Accolade's games didn't actually contain any of Sega's code, and because of the public benefit resulting from Accolade's work (by way of introducing additional competition in the market). This was an important landmark in the legal history of reverse engineering because in this ruling the court essentially authorized reverse engineering for the purpose of interoperability.
The complexity in reversing arises when we try to create an intuitive link between the high-level concepts described earlier and the low-level perspective we get when we look at a program's binary. It is critical that you develop a sort of “mental image” of how high-level constructs such as procedures, modules, and variables are implemented behind the curtains.
Detecting the case where a register is used simply to allow instructions access to specific values is very easy because the register is used only for transferring a value from memory to the instruction or the other way around. In other cases, you will see the same register being repeatedly used and updated throughout a single function. This is often a strong indication that the register is being used for storing a local variable that was defined in the source code.
The stack is frequently used for temporarily saving the value of a register and then restoring the saved value to that register.
It should be noted that when dealing with local variables data is not pushed and popped onto the stack, but instead the stack is accessed using offsets, like a data structure.
In a function call, the caller almost always passes parameters to the callee and is responsible for storing the current instruction pointer so that execution can proceed from its current position once the callee completes.
For reversers, locating heaps in memory and properly identifying heap allocation and freeing routines can be helpful, because it contributes to the overall understanding of the program's data layout. For instance, if you see a call to what you know is a heap allocation routine, you can follow the flow of the procedure's return value throughout the program and see what is done with the allocated block, and so on.
An excellent example of preinitialized data is any kind of hard-coded string inside a program.
(...) hard-coded memory addresses are rarely used for anything other than pointing to the executable's data section.
One of the problems is that most high-level conditional statements are just too lengthy for low-level languages such as assembly language, so they are broken down into sequences of operations. The key to understanding these sequences, the correlation between them, and the high-level statements from which they originated, is to understand the low-level control flow constructs and how they can be used for representing high-level control flow statements.
For most purposes, assembly language is the language of reversing, and mastering it is an essential step in becoming a real reverser, because with most programs assembly language is the only available link to the original source code.
A stack frame can be defined as the current function's stack zone, which resides between the stack pointer (ESP) and the base pointer (EBP).
The base pointer usually points to the stack position right after the return address for the current function. Stack frames are used for gaining quick and convenient access to both local variables and to the parameters passed to the current function.
For detailed information on each instruction refer to the IA-32 Intel Architecture Software Developer's Manual, Volume 2A and Volume 2B Intel2, Intel3. These are the (freely available) IA-32 instruction set reference manuals from Intel.
This is a generic rule in IA-32 instructions: with a few exceptions, most instructions can only take one memory operand.
In essence, CMP simply subtracts Operand2 from Operand1 and discards the result, while setting all of the relevant flags to correctly reflect the outcome of the subtraction. For example, if the result of the subtraction is zero, the Zero Flag (ZF) is set, which indicates that the two operands are equal.
The bottom line is that developing an understanding of the processes undertaken by compilers and the way they “perceive” the code will help in eventually deciphering their output.
I firmly believe that reversers must truly know their systems, and no one can truly claim to understand the system without understanding how software is created and built.
If you'd like to deepen your knowledge of compilers and compiler optimizations, you should check out Cooper Keith D. Copper and Linda Torczon. Engineering a Compiler. Morgan Kaufmann Publishers, 2004, for a highly readable tutorial on compilation techniques, or Muchnick Steven S. Muchnick. Advanced Compiler Design and Implementation. Morgan Kaufmann Publishers, 1997, for a more detailed discussion of advanced compilation materials such as optimizations, and so on.
Because most modern processors can handle multiple instructions at once, data dependencies between individual instructions become an issue. This means that if an instruction performs an operation and stores the result in a register, immediately reading from that register in the following instruction would cause a delay, because the result of the first operation might not be available yet.
The end result is interleaved code, where two instruction sequences dealing with two separate things are interleaved to create one sequence of instructions.
In order to implement the relatively complex IA-32 instructions, the processor has a microcode ROM, which contains the microcode sequences for every instruction in the instruction set. The process of constantly fetching instruction microcode from ROM can create significant performance bottlenecks, so IA-32 processors employ an execution trace cache that is responsible for caching the microcodes of frequently executed instructions.
In order to improve the processor's prediction abilities, IA-32 processors employ a branch trace buffer (BTB) which records the results of the most recent branch instructions processed. This way when a branch is encountered, it is searched in the BTB. If an entry is found, the processor uses that information for predicting the branch.
Kernel mode is basically the Windows term for the privileged processor mode and is frequently used for describing code that runs in privileged mode or memory that is only accessible while the processor is in privileged mode. User mode is the nonprivileged mode: when the system is in user mode, it can only run user-mode code and can only access user-mode memory.
Internally, paging is easy to implement on virtual memory systems. The system must maintain some kind of measurement on when a page was last accessed (the processor helps out with this), and use that information to locate pages that haven't been used in a while. Once such pages are located, the system can flush their contents to a file and invalidate their page-table entries. The contents of these pages in physical memory can then be discarded and the space can be used for other purposes.
Later, when the flushed pages are accessed, the processor will generate page fault (because their page-table entries are invalid), and the system will know that they have been paged out. At this point the operating system will access the paging file (which is where all paged-out memory resides), and read the data back into memory.
In reality, this only works when applications don't actively use more memory than is physically available, because in such cases the system would have to move data back and forth between physical memory and the hard drive. Because hard drives are generally about 1,000 times slower than physical memory, such situations can bring cause systems to run incredibly slowly.
A working set is a per-process data structure that lists the current physical pages that are in use in the process's address space.
It can be said that the memory usage of a process at any given moment can be measured as the total size of its working set. That's generally true, but is a bit of an oversimplification because significant chunks of the average process address space contain shared memory, which is also counted as part of the total working set size. Measuring memory usage in a virtual memory system is not a trivial task!
(...) applications only have a 31-bit address space—the most significant bit is always clear in every address. This provides a tiny reversing hint: A 32-bit number whose first hexadecimal digit is 8 or above is not a valid user-mode pointer.
Caching is implemented in Windows by mapping files into memory and allowing the memory manager to manage the amount of physical memory allocated to each mapped file. When a program opens a file, a section object (see below) is created for it, and it is mapped into the system cache area. When the program later accesses the file using the ReadFile or WriteFile APIs, the file system internally accesses the mapped copy of the file using cache manager APIs such as CcCopyRead and CcCopyWrite.
The Terminal Services component is a Windows service that allows for multiple, remote GUI sessions on a single Windows system. In order to implement this feature, Microsoft has made the Win32 memory space “session private,” so that the system can essentially load multiple instances of the Win32 subsystem. In the kernel, each instance is loaded into the same virtual address, but in a different session space. The session space contains the WIN32K.SYS executable, and various data structures required by the Win32 subsystem. There is also a special session pool, which is essentially a session private paged pool that also resides in this region.
Page Tables and Hyper Space These two regions contain process-specific data that defines the current process's address space.
System Working Set The system working set is a system-global data structure that manages the system's physical memory use (for pageable memory only). It is needed because large parts of the contents of the kernel memory address space are pageable, so the system must have a way of keeping track of the pages that are currently in use. The two largest memory regions that are managed by this data structure are the paged pool and the system cache.
Internally, the kernel uses the System PTE space for mapping device driver executables and for storing kernel stacks (there is one for each thread in the system). Device drivers can allocate System PTE regions by calling the MmAllocateMappingAddress kernel API.
One of the key properties of section objects is that they can be mapped to more than one place. This makes section objects a convenient tool for applications to share memory between them. The system also uses section objects to share memory between the kernel and user-mode processes. This is done by mapping the same section object into both the kernel address space and one or more user-mode address spaces.
Finally, it should be noted that the term “section object” is a kernel concept—in Win32 (and in most of Microsoft's documentation) they are called memory mapped files.
The system uses file-backed section objects for a variety of purposes, including the loading of executable images.
A Virtual Address Descriptor (VAD) tree is the data structure used by Windows for managing each individual process's address allocation. The VAD tree is a binary tree that describes every address range that is currently in use.
Most Windows applications don't directly call VirtualAlloc—instead they allocate a heap block by calling a runtime library function such as malloc or by calling a system heap API such as HeapAlloc.
Viewing objects from user mode, as most applications do, gives them a somewhat mysterious aura. It is important to understand that under the hood all of these objects are merely data structures—they are typically stored in nonpaged pool kernel memory. All objects use a standard object header that describes the basic object properties such as its type, reference count, name, etc and so on. The object manager is not aware of any object-specific data structures, only of the generic header.
Kernel code typically accesses objects using direct pointers to the object data structures, but application programs obviously can't do that. Instead, applications use handles for accessing individual objects. A handle is a process specific numeric identifier which is essentially an index into the process's private handle table.
Along with the object pointer, each handle entry also contains an access mask that determines which types of operations that can be performed on the object using this specific handle.
The object's access mask is a 32-bit integer that is divided into two 16-bit access flag words. The upper word contains generic access flags such as GENERIC_READ and GENERIC_WRITE. The lower word contains object specific flags such as PROCESS_TERMINATE,which allows you to terminate a process using its handle, or KEY_ENUMERATE_SUB_KEYS , which allows you to enumerate the subkeys of an open registry key. All access rights constants are defined in WinNT.H in the Microsoft Platform SDK.
When an object creation API such as CreateMutex is called for an object that already exists, the kernel automatically locates that object in the global table and returns a handle to it. Named objects are arranged in hierarchical directories, but the Win32 API restricts user-mode applications' access to these directories.
This directory (BaseNamedObjects) is where all conventional Win32 named objects, such as mutexes, are stored. All named-object Win32 APIs automatically use this directory—application programs have no control over this.
Some kernel objects are unnamed and are only identified by their handles or kernel object pointers. A good example of such an object is a thread object, which is created without a name and is only represented by handles (from user mode) and by a direct pointer into the object (from kernel mode).
Internally, a thread is nothing but a data structure that has a CONTEXT data structure telling the system the state of the processor when the thread last ran, combined with one or two memory blocks that are used for stack space.
The components that manage threads in Windows are the scheduler and the dispatcher, which are together responsible for deciding which thread gets to run for how long, and for performing the actual context switch when its time to change the currently running thread.
An interesting aspect of the Windows architecture is that the kernel is preemptive and interruptible, meaning that a thread can usually be interrupted while running in kernel mode just like as it can be interrupted while running in user mode.
In many reversing experiences, I've found that it's important to have an understanding of what happens when a process is started. The following provides a brief description of the steps taken by the system in an average process creation sequence. 1.The creation of the process object and new address space is the first step: When a process calls the Win32 API CreateProcess, the API creates a process object and allocates a new memory address space for the process. 2. CreateProcess maps NTDLL.DLL and the program executable (the .exefile) into the newly created address space. 3. CreateProcess creates the process's first thread and allocates stack space for it. 4. The process's first thread is resumed and starts running in the LdrpInitialize function inside NTDLL.DLL. 5.LdrpInitialize recursively traverses the primary executable's import tables and maps into memory every executable that is required for running the primary executable. 6. At this point control is passed into LdrpRunInitializeRoutines, which is an internal NTDLL.DLL routine responsible for initializing all statically linked DLLs currently loaded into the address space. The initialization process consists of calling each DLL's entry point with the DLL_PROCESS_ATTACH constant. 7. Once all DLLs are initialized, LdrpInitialize calls the thread's real initialization routine, which is the BaseProcessStartfunction from KERNEL32.DLL. This function in turn calls the executable's WinMain entry point, at which point the process has completed its initialization sequence.
If you're going to be doing serious reversing of Windows applications, it is going to be important for you to understand the Win32 API. That's because no matter which high-level interface an application employs (if any), it is eventually going to use the Win32 API for communicating with the OS. Some applications will use the Native native API, but that's quite rare—see
The Core Win32 API contains roughly 2000 APIs (it depends on the specific Windows version and on whether or not you count undocumented Win32 APIs). These APIs are divided into three categories: Kernel, USER, and GDI.
Kernel APIs (also called the BASE APIs) are implemented in the KERNEL32.DLL module and include all non-GUI-related services, such as file I/O, memory management, object management, process and thread management, and so on.
GDI APIs are implemented in the GDI32.DLL and include low-level graphics services such as those for drawing a line, displaying a bitmap, and so on. GDI is generally not aware of the existence of windows or controls.
USER APIs are implemented in the USER32.DLL module and include all higher-level GUI-related services such as window-management, menus, dialog boxes, user-interface controls, and so on. All GUI objects are drawn by USER using GDI calls to perform the actual drawing; USER heavily relies on GDI to do its business.
Application programs are never supposed to directly call into the native API—that would break their compatibility with Windows 9 x. This is one of the reasons why Microsoft never saw fit to actually document it;
Also, by not exposing the native API, Microsoft retained the freedom to change and revise it without affecting Win32 applications.
Technically, the native API is a set of functions exported from both NTDLL.DLL (for user-mode callers) and from NTOSKRNL.EXE (for kernel-mode callers). APIs in the native API always start with one of two prefixes: either Nt or Zw, so that functions have names like NtCreateFile or ZwCreateFile. If you're wondering what Zw stands for—I'm sorry, I have no idea. The one thing I do know is that every native API has two versions, an Nt version and a Zw version.
The reason you would want to go through the system-call mechanism when calling an API from kernel-mode kernel mode is to “prove” to the API being called that you're actually calling it from kernel-mode kernel mode. If you don't do that, the API might think it is being called from user-mode code and will verify that all parameters only contain user-mode addresses. This is a safety mechanism employed by the system to make sure user-mode user mode calls don't corrupt the system by passing kernel-memory pointers. For kernel-mode code, calling the Zw APIs is a way to simplify the process of calling functions because you can pass regular kernel-mode pointers.
If you'd like to use or simply understand the workings of the native API, it has been almost fully documented by Gary Nebbett in Windows NT/2000 Native API Reference. Macmillan Technical Publishing, 2000. Nebbett.
The general idea is that the user-mode code invokes a special CPU instruction that tells the processor to switch to its privileged mode (the CPUs terminology for kernel-mode execution) and call a special dispatch routine. This dispatch routine then calls the specific system function requested from user mode.
The following sequence is a typical Windows 2000 system call. ntdll!ZwReadFile: 77f8c552 mov eax,0xa1 77f8c557 lea edx,esp+0x4 77f8c55b int 2e 77f8c55d ret 0x24 The EAX register is loaded with the service number (we'll get to this in a minute), and EDX points to the first parameter that the kernel-mode function receives.
When the int 2e instruction is invoked, the processor uses the interrupt descriptor table (IDT) in order to determine which interrupt handler to call. The IDT is a processor-owned table that tells the processor which routine to invoke whenever an interrupt or an exception takes place. The IDT entry for interrupt number 2E points to an internal NTOSKRNL function called KiSystemService, which is the kernel service dispatcher. KiSystemService verifies that the service number and stack pointer are valid and calls into the specific kernel function requested. The actual call is performed using the KiServiceTable array, which contains pointers to the various supported kernel services. KiSystemService simply uses the request number loaded into EAX as an index into KiServiceTable.
More recent versions of the operating systems use an optimized version of the same mechanism. Instead of invoking an interrupt in order to perform the switch to kernel-mode kernel mode, the system now uses the special SYSENTER instruction in order to perform the switch. SYSENTER is essentially a high-performance kernel-mode switch instruction that calls into a predetermined function whose address is stored at a special model specific register (MSR) called SYSENTER_EIP_MSR. Needless to say, the contents of MSRs can only be accessed from kernel mode. Inside the kernel the new implementation is quite similar and goes through KiSystemService and KiServiceTablein the same way it did in Windows 2000 and older systems. The following is a typical system API in recent versions of Windows such as Windows Server 2003 and Windows XP. ntdll!ZwReadFile: 77f4302f mov eax,0xbf 77f43034 mov edx,0x7ffe0300 77f43039 call edx 77f4303b ret 0x24 This function calls into SharedUserData!SystemCallStub (every system call goes through this function). The following is a disassembly of the code at 7ffe0300. SharedUserData!SystemCallStub: 7ffe0300 mov edx,esp 7ffe0302 sysenter 7ffe0304 ret If you're wondering why this extra call is required (instead of just invoking SYSENTER from within the system API), it's because SYSENTER records no state information whatsoever. In the previous implementation, the invocation of int 2e would store the current value of the EIP and EFLAGS registers. SYSENTER on the other hand stores no state information, so by calling into the SystemCallStub the operating system is recording the address of the current user-mode stub in the stack, so that it later knows where to return. Once the kernel completes the call and needs to go back to user mode, it simply jumps to the address recorded in the stack by that call from the API into SystemCallStub; the RET instruction at 7ffe0304 is never actually executed.
Probably the most important thing to bear in mind when dealing with executable files is that they're relocatable. This simply means that they could be loaded at a different virtual address each time they are loaded (but they can never be relocated after they have been loaded).
The question is, what address should the compiler and linker write as the address to pGlobalVariable while generating the executable? Usually, you would just write a relative address— an address that's relative to the beginning of the file. This way you wouldn't have to worry about where the file gets loaded. The problem is this is a code sequence that gets executed directly by the processor. You could theoretically generate logic that would calculate the exact address by adding the relative address to the base address where the executable is currently mapped, but that would incur a significant performance penalty. Instead, the loader just goes over the code and modifies all absolute addresses within it to make sure that they point to the right place.
Relocations are important for several reasons. First of all, they're the reason why there are never absolute addresses in executable headers, only in code. Whenever you have a pointer inside the executable header, it'll always be in the form of a relative virtual address (RVA). An RVA is just an offset into the file. When the file is loaded and is assigned a virtual address, the loader calculates real virtual addresses out of RVAs by adding the module's base address (where it was loaded) to an RVA.
An executable image is divided into individual sections in which the file's contents are stored. Sections are needed because different areas in the file are treated differently by the memory manager when a module is loaded.
Because individual sections often have different access settings defined in the executable header, and because the memory manager must apply these access settings when an executable image is loaded, sections must typically be page-aligned when an executable is loaded into memory. On the other hand, it would be wasteful to actually align executables to a page boundary on disk—that would make them significantly bigger than they need to be. Because of this, the PE header has two different kinds of alignment fields: Section alignment and file alignment. Section alignment is how sections are aligned when the executable is loaded in memory and file alignment is how sections are aligned inside the file, on disk. Alignment is important when accessing the file because it causes some interesting phenomena. The problem is that an RVA is relative to the beginning of the image when it is mapped as an executable (meaning that distances are calculated using section alignment). This means that if you just open an executable as a regular file and try to access it, you might run into problems where RVAs won't point to the right place. This is because RVAs are computed using the file's section alignment (which is effectively its in-memory alignment), and not using the file alignment.
A PE file starts with the good old DOS header. This is a common backward-compatible design that ensures that attempts to execute PE files on DOS systems will fail gracefully. In this case failing gracefully means that you'll just get the well-known “This program cannot be run in DOS mode” message.
When the importing module needs to call into an imported function, the calling code typically looks like this: call SomeAddress Where SomeAddress is a pointer into the executable import address table (IAT).
The I/O system is layered, which means that for each device there can be multiple device drivers that are stacked on top of each other.
The Win32 subsystem is the component responsible for every aspect of the Windows user interface. This starts with the low-level graphics engine, the graphics device interface (GDI), and ends with the USER component, which is responsible for higher-level GUI constructs such as windows and menus, and for processing user input.
First of all, it's important to realize that the components considered the Win32 subsystem are not responsible for the entire Win32 API, only for the USER and GDI portions of it. As described earlier, the BASE API exported from KERNEL32.DLL is implemented using direct calls into the native API, and has really nothing to do with the Win32 subsystem.
The Win32 subsystem is implemented inside the WIN32K.SYS kernel component and is controlled by the USER32.DLL and GDI32.DLL user components.
It can be helpful for reversers to become familiar with USER and GDI and with the general architecture of the Win32 subsystem because practically all user-interaction flows through them. Suppose, for example, that you're trying to find the code in a program that displays a certain window, or the code that processes a certain user event. The key is to know how to track the flow of such events inside the Win32 subsystem. From there it becomes easy to find the program code that's responsible for receiving or generating such events.
Because USER and GDI are both old components that were ported from ancient versions of Windows, they don't use the kernel object manager discussed earlier. Instead they each use their own little object manager mechanism.
Handles to Win32 objects such as windows and device contexts are essentially indexes into these object tables. The tables are stored and managed in kernel memory, but are also mapped into each process's address space for read-only access from user mode.
Because the USER and GDI handle tables are global, and because handles are just indexes into those tables, it is obvious that unlike kernel object handles, both USER and GDI handles are global—if more than one process needs to access the same objects, they all share the same handles. In reality, the Win32 subsystem doesn't always allow more than one process to access the same objects;
There are two basic types of exceptions: hardware exceptions and software exceptions. Hardware exceptions are exceptions generated by the processor, for example when a program accesses an invalid memory page (a page fault) or when a division by zero occurs. A software exception is generated when a program explicitly generates an exception in order to report an error.
In Windows, the throw keyword is implemented using the RaiseException Win32 API, which goes down into the kernel and follows a similar code path as a hardware exception, eventually returning to user mode to notify the program of the exception.
Structured exception handling means that the operating system provides mechanisms for “distributing” exceptions to applications in an organized manner. Each thread is assigned an exception-handler list, which is a list of routines that can deal with exceptions when they occur. When an exception occurs, the operating system calls each of the registered handlers and the handlers can decide whether they would like to handle the exception or whether the system should keep on looking.
The exception handler list is stored in the thread information block (TIB) data structure, which is available from user mode and contains the following fields: _NT_TIB: +0x000 ExceptionList : 0x0012fecc +0x004 StackBase : 0x00130000 +0x008 StackLimit : 0x0012e000 +0x00c SubSystemTib : (null) +0x010 FiberData : 0x00001e00 +0x010 Version : 0x1e00 +0x014 ArbitraryUserPointer : (null) +0x018 Self : 0x7ffde000
How does a thread find its own TIB in runtime? On IA-32 processors, Windows uses the FS segment register as a pointer to the currently active thread-specific data structures. The current thread's TIB is always available at FS:0.
The ExceptionList member is the one of interest; it is the head of the current thread's exception handler list. When an exception is generated, the processor calls the registered handler from the IDT.
When an invalid memory address is accessed (an invalid memory address is one that doesn't have a valid page-table entry), the processor generates a page-fault interrupt (interrupt #14), and invokes the interrupt handler from entry 14 at the IDT. In Windows, this entry usually points to the KiTrap0E function in the Windows kernel. KiTrap0E decides which type of page fault has occurred and dispatches it properly. For user-mode page faults that aren't resolved by the memory manager (such as faults caused by an application accessing an invalid memory address), Windows calls into a user-mode exception dispatcher routine called KiUserExceptionDispatcher in NTDLL.DLL. KiUserExceptionDispatcher calls into RtlDispatchException, which is responsible for going through the linked list at ExceptionList and looking for an exception handler that can deal with the exception. The linked list is essentially a chain of _EXCEPTION_REGISTRATION_RECORD data structures, which are defined as follows: _EXCEPTION_REGISTRATION_RECORD: +0x000 Next : Ptr32 _EXCEPTION_REGISTRATION_RECORD +0x004 Handler : Ptr32 A bare-bones exception handler set up sequence looks something like this: 00411F8A push ExceptionHandler 00411F8F mov eax,dword ptr fs:00000000h 00411F95 push eax 00411F96 mov dword ptr fs:0,esp This sequence simply adds an _EXCEPTION_REGISTRATION_RECORD entry into the current thread's exception handler list. The items are stored on the stack.
In real-life you will rarely run into simple exception handler setup sequences such as the one just shown. That's because compilers typically augment the operating system's mechanism in order to provide support for nested exception-handling blocks and for multiple blocks within the same function. In the Microsoft compilers, this is done by routing exception to the _except_handler3 exception handler, which then calls the correct exception filter and exception handler based on the current function's layout. To implement this functionality, the compiler manages additional data structures that manage the hierarchy of exception handlers within a single function. The following is a typical Microsoft C/C++ compiler SEH installation sequence: 00411F83 push 0FFFFFFFFh 00411F85 push 425090h 00411F8A push offset @ILT+420(__except_handler3) (4111A9h) 00411F8F mov eax,dword ptr fs:00000000h 00411F95 push eax 00411F96 mov dword ptr fs:0,esp As you can see, the compiler has extended the _EXCEPTION_REGISTRATION_RECORD data structure and has added two new members. These members will be used by _except_handler3 to determine which handler should be called.
Beyond the frame-based exception handlers, recent versions of the operating system also support a vector of exception handlers, which is a linear list of handlers that are called for every exception, regardless which code generated it. Vectored exception handlers are installed using the Win32 API AddVectoredExceptionHandler.
Imagine an application making a sequence of system API calls. The application is essentially talking to the operating system, and the API is the language; if you understand the basics of the API in question, you can tune in to that conversation and find out what the application is saying. . . .
If you'd like to proceed to develop a better understanding of operating systems, check out Operating System, Design and Implementation by Andrew S. Tanenbaum and Albert S. Woodhull Tanenbaum2 Andrew S. Tanenbaum, Albert S. Woodhull, Operating Systems: Design and Implementation, Second Edition, Prentice Hall, 1997 for a generic study of operating systems concepts. For highly detailed information on the architecture of NT-based Windows operating systems, see Microsoft Windows Internals, Fourth Edition: Microsoft Windows Server 2003, Windows XP, and Windows 2000 by Mark E. Russinovich and David A. Solomon Russinovich. That book is undoubtedly the authoritative guide on the Windows architecture and internals.
Generally speaking, there are two fundamental reversing methodologies: offline analysis and live analysis.
The downside of offline code analysis is usually that a better understanding of the code is required (compared to live analysis) because you can't see the data that the program deals with and how it flows. You must guess what type of data the code deals with and how it flows based on the code. Offline analysis is typically a more advanced approach to reversing.
Generally, I'd say that live analysis is the better approach for beginners because it provides a lot more data to work with.
In order to properly distinguish code from data, disassemblers must use recursive traversal instead of the conventional linear sweep Benjamin Schwarz, Saumya Debray, and Gregory Andrews. Disassembly of Executable Code Revisited. Proceedings of the Ninth Working Conference on Reverse Engineering, 2002. Schwarz. Briefly, the difference between the two is that recursive traversal actually follows the flow of the code, so that an address is disassembled only if it is reachable from the code disassembled earlier. A linear sweep simply goes instruction by instruction, which means that any data in the middle of the code could potentially confuse the disassembler.
Software breakpoints are instructions added into the program's code by the debugger at runtime. These instructions make the processor pause program execution and transfer control to the debugger when they are reached during execution. Hardware breakpoints are a special CPU feature that allow the processor to pause execution when a certain memory address is accessed, and transfer control to the debugger. This is an especially powerful feature for reversers because it can greatly simplify the process of mapping and deciphering data structures in a program.
Being restricted to viewing user-mode code is not usually a problem unless the product you're debugging has its own kernel-mode components (such as device drivers).
OllyDbg's greatest strength is in its disassembler, which provides powerful code-analysis features. OllyDbg's code analyzer can identify loops, switch blocks, and other key code structures. It shows parameter names for all known functions and APIs, and supports searching for cross-references between code and data—in all possible directions. In fact, it would be fair to say that Olly has the best disassembly capabilities of all debuggers I have worked with (except for the IDA Pro debugger), including the big guns that run in kernel mode.
OllyDbg also includes a built-in assembling and patching engine, which makes it a cracker's favorite. It is possible to type in assembly language code over any area in a program and then commit the changes back into the executable if you so require. Alternatively, OllyDbg can also store the list of patches performed on a specific program and apply some or all of those patches while the program is being debugged—when they are required.
Unsurprisingly, one place where WinDbg is unbeatable and far surpasses OllyDbg is in its integration with the operating system. WinDbg has powerful extensions that can provide a wealth of information on a variety of internal system data structures.
I personally wouldn't purchase IDA just for its debugging capabilities, but having a debugger and a highly capable disassembler in one program definitely makes IDA the Swiss Army Knife of the reverse engineering community.
PEBrowse offers multiple informative views on the process such as a detailed view of the currently active memory heaps and the allocated blocks within them.
what WinDbg looks like when it is used for kernel-mode debugging. Notice that the disassembly window on the right is disassembling kernel-mode code from the nt module (this is ntoskrnl.exe, the Windows kernel).
SoftICE is also compatible with WinDbg extensions and can translate extensions DLLs and make their commands available within the SoftICE environment.
SoftICE is an interesting technology, and many people don't really understand how it works, so let's run a brief overview. Fundamentally, SoftICE is a Windows kernel-mode driver. When SoftICE is loaded, it hooks the system's keyboard driver, and essentially monitors keystrokes on the system. When it detects that the SoftICE hotkey has been hit (the default is Ctrl+D), it manually freezes the system's current state and takes control over it. It starts by drawing a window over whatever is currently displayed on the screen. It is important to realize that this window is not in any way connected to Windows, because Windows is completely frozen at this point. SoftICE internally manages this window and any other user-interface elements required while it is running. When SoftICE is opened, it disables all interrupts, so that thread scheduling is paused, and it takes control of all processors in multiprocessor systems. This effectively freezes the system so that no code can run other than SoftICE itself.
Many people wonder about SoftICE's name, and it is actually quite interesting. ICE stands for in circuit emulator, which is a popular tool for performing extremely low-level debugging. The idea is to replace the system's CPU with an emulator that acts just like the real CPU and is capable of running software, except that it can be debugged at the hardware level. This means that the processor can be stopped and that its state can be observed at any time. SoftICE stands for a Software ICE, which implies that SoftICE is like a software implementation of an in circuit emulator.
The idea is that by learning reversing techniques, software developers can more efficiently interoperate with third-party code (which is something every software developer does every day). That's possible because reversing provides the ultimate insight into the third-party's code—it takes you beyond the documentation.
In the next few chapters, you can expect to see quite a few longish, uncommented assembly language code listings, followed by detailed explanations of those listings. I have intentionally avoided commenting any of the code, because that would be outright cheating. The whole point is that you will look at raw assembly language code just as it will be presented to you in a real reversing session, and try to extract the information you're seeking from that code. I've made these analysis sessions very detailed, so you can easily follow the comprehension process as it takes place.
Once you find the name of an undocumented API and the name of the DLL that exports it, it's time to look for binaries that use it. Finding an executable that calls the API will serve two purposes. First, it might shed some additional light on what the API does. Second, it provides a live sample of how the API is used and exactly what data it receives as input and what it returns as output.
It is possible that one of these parameters would be larger than 4 bytes, in which case the function receives less than five parameters, but it can't possibly be more than five because parameters are 32-bit aligned.
The current value of EBP is saved on the stack, and EBP takes the value of ESP. This allows for convenient access to the parameters that were passed on the stack regardless of the current value of ESP while running the function (ESP constantly changes whenever the function pushes parameters into the stack while calling other functions).
Typically, a function would also allocate room for local variables by subtracting ESP with the number of bytes needed for local variable storage, but this doesn't happen in this function, indicating that the function doesn't store any local variables in the stack.
IA-32 processors support special memory management constructs called segments, but these are not used in Windows and can be safely ignored in most cases. There are several segment registers in IA-32 processors: CS, DS, FS, ES, and SS. On Windows, any mentioning of any of those can be safely ignored except for FS, which allows access to a small area of thread-local memory. Memory accesses that start with FS: are usually accessing that thread-local area.
LEA (load effective address) is essentially an arithmetic instruction—it doesn't perform any actual memory access, but is commonly used for calculating addresses (though you can calculate general purpose integers with it). Don't let the DWORD PTR prefix fool you; this instruction is purely an arithmetic operation.
Interleaved code means that instructions aren't placed in the code in their natural order, but instead pairs of interdependent instructions are interleaved so that in runtime the CPU has time to complete the first instruction before it must execute the second one. In this case, you can tell that the code is interleaved because the conditional jump doesn't immediately follow the CMP instruction.
This time, LEA is used simply to perform an EBX = EDI + 1. Typically, compilers would use INC EDI, but in this case the compiler wanted to keep both the original and the incremented value, so LEA is an excellent choice. It increments EDI by one and stores the result in EBX—the original value remains in EDI.
Notice that the jump target address, ntdll.7C962559, is the same as the address of the previous conditional jump. This is a strong indication that the two jumps are part of what was a single compound conditional statement in the source code. They are just two conditions tested within a single conditional statement.
To me, this is the thrill of reversing—one by one gathering pieces of evidence and bringing them together to form partial explanations that slowly evolve into a full understanding of the code.
How would you conditionally skip over so much code in a high-level language? Simple, the condition tested in the assembly language code is the opposite of what was tested in the source code. That's because the processor needs to know whether to skip code, and high-level languages have a different perspective—which terms must be satisfied in order to enter a certain conditional block.
Whenever you find a conditional jump that skips a code block that ends with a forward-pointing unconditional JMP, you're probably looking at an if-else block. The block being skipped is the if block, and the code after the unconditional JMP is the else block.
The end of the else block is marked by the target address of the unconditional JMP.
You can see a JE (which is jump if equal) after the subtraction because subtraction and comparison are the same thing, except that in a comparison the result of the subtraction is discarded, and only the flags are kept.
Interleaved code means that instructions aren't placed in the code in their natural order, but instead pairs of interdependent instructions are interleaved so that in runtime the CPU has time to complete the first instruction before it must execute the second one. In this case, you can tell that the code is interleaved because the conditional jump doesn't immediately follow the CMP instruction.
This time, LEA is used simply to perform an EBX = EDI + 1. Typically, compilers would use INC EDI, but in this case the compiler wanted to keep both the original and the incremented value, so LEA is an excellent choice. It increments EDI by one and stores the result in EBX—the original value remains in EDI.
Notice that the jump target address, ntdll.7C962559, is the same as the address of the previous conditional jump. This is a strong indication that the two jumps are part of what was a single compound conditional statement in the source code. They are just two conditions tested within a single conditional statement.
To me, this is the thrill of reversing—one by one gathering pieces of evidence and bringing them together to form partial explanations that slowly evolve into a full understanding of the code.
How would you conditionally skip over so much code in a high-level language? Simple, the condition tested in the assembly language code is the opposite of what was tested in the source code. That's because the processor needs to know whether to skip code, and high-level languages have a different perspective—which terms must be satisfied in order to enter a certain conditional block.
Whenever you find a conditional jump that skips a code block that ends with a forward-pointing unconditional JMP, you're probably looking at an if-else block. The block being skipped is the if block, and the code after the unconditional JMP is the else block.
The end of the else block is marked by the target address of the unconditional JMP.
You can see a JE (which is jump if equal) after the subtraction because subtraction and comparison are the same thing, except that in a comparison the result of the subtraction is discarded, and only the flags are kept.
# Unabomber Manifesto (Theodore Kaczynski)
Caloni, 2023-06-25 books philosophy [up] [copy]Theodore Kaczynski, conhecido como Unabomber, apareceu morto esses dias em sua cela. Ele estava preso pagando uma pena maior que a vida. Em sua época gloriosa ele forçou um jornal a publicar seu manifesto, um livro com centenas de parágrafos explicando o porquê da revolução industrial ter sido um desastre para a raça humana e como o futuro não deve ser melhor.
Eu não conhecia seus pensamentos e comecei a ler. Me interessei muito, não consegui parar. Sua didática e argumentação são melhores que a maioria do conteúdo da mídia atual. Se trata de um ensaio sobre sociedade e política amplo e ousado. Ele monta suas hipóteses sobre a conhecida doença do esquerdismo, e toma o cuidado de abrir ressalvas de que não se trata de atacar a opinião da esquerda, mas o seu psicológico, e como isso é um sintoma de algo maior.
Porém, próximo do final, ele se parece mais com o maluco fanático de plantão. É curioso como alguém tão loquaz pira na batatinha. Bom, descanse em paz. Um minuto de silêncio para refletirmos a cada ano se este mundo pós-escassez é realmente o que desejamos para nossos filhos.
29. (...) In all ESSENTIAL respects most leftists of the oversocialized type want to make the black man conform to white, middle-class ideals. They want to make him study technical subjects, become an executive or a scientist, spend his life climbing the status ladder to prove that black people are as good as white. They want to make black fathers “responsible,” they want black gangs to become nonviolent, etc. But these are exactly the values of the industrial-technological system. The system couldn’t care less what kind of music a man listens to, what kind of clothes he wears or what religion he believes in as long as he studies in school, holds a respectable job, climbs the status ladder, is a “responsible” parent, is nonviolent and so forth.
32. The problems of the leftist are indicative of the problems of our society as a whole. Low self-esteem, depressive tendencies and defeatism are not restricted to the left. Though they are especially noticeable in the left, they are widespread in our society.
44. But for most people it is through the power process having a goal, making an AUTONOMOUS effort and attaining the goal -- that self-esteem, self-confidence and a sense of power are acquired. When one does not have adequate opportunity to go through the power process the consequences are (depending on the individual and on the way the power process is disrupted) boredom, demoralization, low self-esteem, inferiority feelings, defeatism, depression, anxiety, guilt, frustration, hostility, spouse or child abuse, insatiable hedonism, abnormal sexual behavior, sleep disorders, eating disorders. etc. 6
50. The conservatives are fools: They whine about the decay of traditional values, yet they enthusiastically support technological progress and economic growth. Apparently it never occurs to them that you can’t make rapid, drastic changes in the technology and the economy of a society without causing rapid changes in all other aspects of the society as well, and that such rapid changes inevitably break down traditional values.
66. Today people live more by virtue of what the system does FOR them or TO them than by virtue of what they do for themselves. And what they do for themselves is done more and more along channels laid down by the system. Opportunities tend to be those that the system provides, the opportunities must be exploited in accord with rules and regulations 13, and techniques prescribed by experts must be followed if there is to be a chance of success.
86. But even if most people in industrial-technological society were well satisfied, we (FC) would still be opposed to that form of society, because (among other reasons) we consider it demeaning to fulfill one’s need for the power process through surrogate activities or through identification with an organization, rather than through pursuit of real goals.
132. It is well known that people generally work better and more persistently when striving for a reward than when attempting to avoid a punishment or negative outcome. Scientists and other technicians are motivated mainly by the rewards they get through their work. But those who oppose technological invasions of freedom are working to avoid a negative outcome, consequently there are few who work persistently and well at this discouraging task.
144. Thus human nature has in the past put certain limits on the development of societies. People could be pushed only so far and no farther. But today this may be changing, because modern technology is developing ways of modifying human beings.
147. Entertainment provides modern man with an essential means of escape. While absorbed in television, videos, etc., he can forget stress, anxiety, frustration, dissatisfaction. Many primitive peoples, when they don’t have work to do, are quite content to sit for hours at a time doing nothing at all, because they are at peace with themselves and their world. But most modern people must be constantly occupied or entertained, otherwise they get “bored,” i.e., they get fidgety, uneasy, irritable.
158. It presumably would be impractical for all people to have electrodes inserted in their heads so that they could be controlled by the authorities. But the fact that human thoughts and feelings are so open to biological intervention shows that the problem of controlling human behavior is mainly a technical problem; a problem of neurons, hormones and complex molecules; the kind of problem that is accessible to scientific attack. Given the outstanding record of our society in solving technical problems, it is overwhelmingly probable that great advances will be made in the control of human behavior.
162. The system is currently engaged in a desperate struggle to overcome certain problems that threaten its survival, among which the problems of human behavior are the most important. If the system succeeds in acquiring sufficient control over human behavior quickly enough, it will probably survive. Otherwise it will break down. We think the issue will most likely be resolved within the next several decades, say 40 to 100 years.
173. But we are suggesting neither that the human race would voluntarily turn power over to the machines nor that the machines would willfully seize power. What we do suggest is that the human race might easily permit itself to drift into a position of such dependence on the machines that it would have no practical choice but to accept all of the machines’ decisions. As society and the problems that face it become more and more complex and as machines become more and more intelligent, people will let machines make more and more of their decisions for them, simply because machine-made decisions will bring better results than man-made ones. Eventually a stage may be reached at which the decisions necessary to keep the system running will be so complex that human beings will be incapable of making them intelligently. At that stage the machines will be in effective control. People won’t be able to just turn the machine off, because they will be so dependent on them that turning them off would amount to suicide.
174. On the other hand it is possible that human control over the machines may be retained. In that case the average man may have control over certain private machines of his own, such as his car or his personal computer, but control over large systems of machines will be in the hands of a tiny elite -- just as it is today, but with two differences. Due to improved techniques the elite will have greater control over the masses; and because human work will no longer be necessary the masses will be superfluous, a useless burden on the system. If the elite is ruthless they may simply decide to exterminate the mass of humanity. If they are humane they may use propaganda or other psychological or biological techniques to reduce the birth rate until the mass of humanity becomes extinct, leaving the world to the elite. Or, if the elite consists of soft-hearted liberals, they may decide to play the role of good shepherds to the rest of the human race. They will see to it that everyone’s physical needs are satisfied, that all children are raised under psychologically hygienic conditions, that everyone has a wholesome hobby to keep him busy, and that anyone who may become dissatisfied undergoes “treatment” to cure his “problem.” Of course, life will be so purposeless that people will have to be biologically or psychologically engineered either to remove their need for the power process or to make them “sublimate” their drive for power into some harmless hobby. These engineered human beings may be happy in such a society, but they most certainly will not be free. They will have been reduced to the status of domestic animals.
184. Whatever kind of society may exist after the demise of the industrial system, it is certain that most people will live close to nature, because in the absence of advanced technology there is no other way that people CAN live. To feed themselves they must be peasants or herdsmen or fishermen or hunters, etc. And, generally speaking, local autonomy should tend to increase, because lack of advanced technology and rapid communications will limit the capacity of governments or other large organizations to control local communities.
215. The anarchist 34 too seeks power, but he seeks it on an individual or small-group basis; he wants individuals and small groups to be able to control the circumstances of their own lives. He opposes technology because it makes small groups dependent on large organizations.
4. (Paragraph 28) Women are encouraged to have careers because their talents are useful to the system and, more importantly, because by having regular jobs women become better integrated into the system and tied directly to it rather than to their families. This helps to weaken family Page 34 solidarity. (The leaders of the system say they want to strengthen the family, but they really mean is that they want the family to serve as an effective tool for socializing children in accord with the needs of the system.
6. (Paragraph 44) Some of the symptoms listed are similar to those shown by caged animals. To explain how these symptoms arise from deprivation with respect to the power process: common-sense understanding of human nature tells one that lack of goals whose attainment requires effort leads to boredom and that boredom, long continued, often leads eventually to depression. Failure to attain goals leads to frustration and lowering of self-esteem. Frustration leads to anger, anger to aggression, often in the form of spouse or child abuse. It has been shown that long-continued frustration commonly leads to depression and that depression tends to cause guilt, sleep disorders, eating disorders and bad feelings about oneself. Those who are tending toward depression seek pleasure as an antidote; hence insatiable hedonism and excessive sex, with perversions as a means of getting new kicks. Boredom too tends to cause excessive pleasure-seeking since, lacking other goals, people often use pleasure as a goal. See accompanying diagram.
7. (Paragraph 52) A partial exception may be made for a few passive, inward-looking groups, such as the Amish, which have little effect on the wider society. Apart from these, some genuine small-scale communities do exist in America today. For instance, youth gangs and “cults.” Everyone regards them as dangerous, and so they are, because the members of these groups are loyal primarily to one another rather than to the system, hence the system cannot control them. Or take the gypsies. The gypsies commonly get away with theft and fraud because their loyalties are such that they can always get other gypsies to give testimony that “proves” their innocence.
33. (Paragraph 195) The economic and technological structure of a society are far more important than its political structure in determining the way the average man lives (see paragraphs 95, 119 and Notes 16, 18).
# Write, merge, publish
Caloni, 2023-06-25 coding [up] [copy]Hoje provei uma ideia ainda melhor que usar a awklib integrada com uma solução C++: o publicador de conteúdo ser um plugin do gawk. Dessa forma o script de transformação de texto está totalmente nas mãos do desenvolvedor (eu) e a velocidade não é impactada nunca (exceto se eu quiser rodar awk em multithreading).
A ideia de arquitetura que está sendo seguida meio por acaso pode ser o core do novo publicador. Dois componentes: merge e publish.
O merge é o componente que obtém conteúdo de N fontes e transforma em um arquivo único em um formato qualquer. Por que único? Porque múltiplos arquivos trabalham mal no SO e o dia a dia de um blogger é muito mais fácil através de um `journal.txt` do que ficar se enveredando nas referências que o sistema de publicação te obriga a usar.
O publish é a transformação do arquivo de texto único para N destinos diferentes: um ou mais blogues e livros, Telegram, RSS, Twitter. Não importa. A definição dos destinos e feito no próprio script awk em conjunto com sua transformação. Por que isso? Porque um escritor não deve se limitar a um único formato. Seu único objetivo na vida é escrever. Seus metadados e o formato do seu texto irão definir para onde vai o conteúdo, mas ele não precisa se preocupar com isso.