Em que circunstâncias posso usar o rundll32 para invocar uma função em uma DLL?

5

Gostaria de invocar a funcionalidade encontrada em várias DLLs do Windows na linha de comando. Parece que o utilitário rundll32 fará o que eu preciso - ele usa um nome de DLL e um nome de função e executa essa função com parâmetros.

Eu certamente espero que não haja problemas com isso. Quais funções posso usar rundll32 on?

    
por Ben N 09.05.2016 / 00:10

1 resposta

5

Quase certamente haverá problemas.

Que funções posso usar rundll32 on?

Bem, optimamente, você não o usaria de todo - é obsoleto :

Rundll32 is a leftover from Windows 95, and it has been deprecated since at least Windows Vista because it violates a lot of modern engineering guidelines. If you run something via Rundll32, then you lose the ability to tailor the execution environment to the thing you’re running.

rundll32 é projetado apenas para chamar um tipo muito específico de função, especificamente, funções que criam uma janela e processam mensagens de janela. Este documento da Microsoft sobre a interface rundll32 explica que a função que você está chamando deve < use um HWND , um HINSTANCE , um LPSTR e um int (nessa ordem), deve usar a convenção de chamada _stdcall / CALLBACK e não deve retornar nada ( void ).

Consulte a documentação da MSDN sobre a função que você deseja chamar para ver se ela possui essa assinatura. Por exemplo, ExitWindowsEx não em forma. Na verdade, não consigo encontrar uma única função com essa assinatura documentada.

Se você não tem certeza do que significa tudo isso, você pode pular a próxima seção e ir para a final.

O que pode dar errado se eu usá-lo em outras funções?

Lembre-se de toda essa coisa de assinatura de função? rundll32 assume que a função que você está tentando chamar tem a assinatura certa , não importa se esse é realmente o caso. Quando sua suposição está errada, coisas relacionadas a pilha seriamente bizarras podem continuar. A pilha é um local de memória que armazena parâmetros passados entre funções.

As assinaturas de função não combinadas resultarão na interpretação dos dados fornecidos por rundll32 como algo diferente devido ao local onde a função espera que seus parâmetros estejam na pilha. O primeiro datum rundll32 supplies é um identificador de janela, que é atribuído de maneira não determinística. Portanto, se você usar de forma incorreta rundll32 , estará efetivamente transmitindo dados aleatórios como o primeiro parâmetro . Naturalmente, isso pode não apenas afetar o primeiro parâmetro da função vítima, porque diferentes tipos de dados ocupam diferentes quantidades de espaço. Outras leituras: O que pode dar errado quando você discorda da convenção de chamada?

Os demais parâmetros não funcionam melhor. Mesmo se você fornecer uma linha de comando para a função via rundll32 , ela não será analisada nos tipos de dados apropriados para a função. Em vez disso, rundll32 apenas pega todo o texto "extra", congestiona-o em uma variável de string e passa um ponteiro para esses dados para a função como um parâmetro posterior. Cabe à função analisar o texto. Portanto, não há esperança de invocar funções arbitrárias com argumentos fornecidos pelo usuário com rundll32 .

Não é um desastre completo se a função alvo não espera parâmetros, mas você ainda está bagunçando a pilha. Existe código em rundll32 para lidar com isso , mas isso não dar-lhe uma desculpa para continuar abusando dele.

Se você estiver usando rundll32 para invocar uma função compatível em uma DLL de terceiros projetada para ser usada dessa forma, ainda assim poderá ter problemas. rundll32 sempre opta por todos os novos recursos do Windows (por exemplo, Prevenção de Execução de Dados ), que pode introduzir alterações que o código de terceiros não foi projetado para; é por isso que o comportamento é opt-in.

Felizmente, existe uma maneira melhor de fazer o que você quer.

O que posso fazer em vez disso?

Tentando bloquear a estação de trabalho ( user32.dll,LockWorkStation )? Apenas execute tsdiscon .

Tentando desligar o sistema ( user32.dll,ExitWindowsEx )? Use o utilitário shutdown com os sinalizadores apropriados - consulte shutdown /? para obter ajuda.

Você é um desenvolvedor de aplicativos e está tentando invocar uma função DLL sem gravar um novo EXE? Escreva esse EXE (provavelmente em C ++).

Tentando executar outra coisa? Meu utilitário de código aberto SprintDLL suporta listas de parâmetros especificadas pelo usuário, várias convenções de chamada e scripts para trabalhar com várias funções e suas saídas. Se você preferir usar apenas ferramentas incluídas no Windows, você pode fazer P / Invoke with PowerShell .

This question and answer were written as a reference usable for correcting those who suggest using rundll32 in a dubious fashion. If you see people abusing rundll32, give them a link to this page!

    
por 09.05.2016 / 00:10