News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Reading and writing data to a pipe

Started by colinr, September 04, 2011, 06:33:04 PM

Previous topic - Next topic

colinr

Just seen your last post, text files again would be an issue as I would still have to implement forced waits to allow the text file to be written, I'll have a look at pre patching diskpart first rather than on the fly.  This is not too much of an issue as one of the forensics guys at MS is in on this project anyway and there has been substatial patching to the vds anyway to maintain forensic soundness

dedndave

here are a few questions.....

1) what is the minimum OS the program is required to run under

2) you want just these 2 functions ?
   a) change drive letter
   b) set/clear read-only attribute

3) do you intend to sell it ?
   (if not, we can use all kinds of stuff)

dedndave

changing a drive letter doesn't look that bad....

                                  operation: function used

         get and store the volume GUID path: GetVolumeNameForVolumeMountPoint
                    remove the drive letter: DeleteVolumeMountPoint
assign new drive letter to stored GUID path: SetVolumeMountPoint

Notes:
1) drive letter strings must be in the form "X:\",0
2) the GUID string can be up to 50 bytes long
3) good idea to make sure the target letter is not in use prior to beginning   :P

colinr

@dedndave, There is no money in the project, it's a free tool for the forensics community, actually the home page is here: http://winfe.wordpress.com/

It just so happens that the DLL that i use at the moment has become redundant due to it not being finished, therefore, I have had to take this radical step at a late stage in the game to actually get something that can be released.

I've looked at the drive letter assignment stuff and it does work as I've tried it, however, the Virtual Disk Service does not return information that is useful, for instance, the disk/volume GUID's appear to be different and //./PhysicalDrive0 is not always the same as the disk that diskpart referrs to as disk 0.

I am going to have a look at modifying diskpart somehow to redirect to my code, whilst not the perfect way of doing things, it would be perfect for me, especially as it's running in a custom boot disk environment.

The only question I have is, how do I set one of the Int vectors to contain a pointer to my code?

Thanks again.

qWord

hi,
I've made a quick test with DiskPart.exe, which requires Administrator rights. If your application has not this rights, you can't redirect the output to your application - probably your debugger runs as adminstrator(?). The following application redirect the output to it's own console, if it runs as Admin:
include masm32rt.inc
.code
main proc
LOCAL sui:STARTUPINFO
LOCAL pi:PROCESS_INFORMATION

invoke RtlZeroMemory,ADDR sui,SIZEOF sui
mov sui.cb,SIZEOF sui
fn CreateProcess,"DiskPart.exe",0,0,0,0,0,0,"C:\Windows\System32",ADDR sui,ADDR pi

invoke WaitForSingleObject,pi.hProcess,-1

inkey
exit
main endp
end main
FPU in a trice: SmplMath
It's that simple!

colinr

Thanks qWord.

I've actually kind of got that far, the problem arises when I come to read the responces via the pipe, without some sort of delay, i read back before diskpart has actually finished outputting its text.

I cant open a new instance of diskpart for each command that i wish to execute as it would just impose too much delay.

I intend to pass multiple commands, one at a time, and then readback the results of these commands all in a single session.

hutch--

Colin,

That type of technology was viable in the real mode DOS days but is not even close to useful in a protected mode OS. Cross process access is difficult at best due to the threading and protection mechanisms built into the OS. Getting piped output is viable then displaying it in whatever way you like afterwards. You can point it at a console, write it to a GUI Window or a control in a GUI window.

Its a 2 part operation, get the data from the external running APP then display it in a convenient form.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

colinr

Thanks Hutch,

Protected mode did cross my mind and I could see the problems you described.

So back to my original problem, when I issue a command to diskpart such as 'List Disk', it has not finished the operation before I attempt to read the outputted text back through the pipe (the buffer is still empty). What is the best way for me to detect that diskpart has completed the operation.  The text returned is also dynamic, so that I will never know how many bytes are due to be returned.

Would PeekNamedPipe meet with my criteria with a few milliseconds delay between subsequent calls as the output will always end with 'DISKPART>'.  If it would work, I dare say I would need to add some kind of additional delay just in case diskpart crashes and does not return anything, otherwise i will end up in a dreaded infinite loop!

I really do wish I could learn C++ as all the API's for the Virtual Disk Service are provided  :'(

Colin.

dedndave

i would try to get away from using DiskPart   :U

colinr

dedndave,

I wish i could but it offers all of the VDS services that I require, i've never been able to find an IOCTL code to set a disk to read-only.

It's a case of either learning C++ in super quick time or write a kernel mode driver which just the thought of, scares me to death!!

I'll have another play with it when I get the time to apply myself to it.

Colin.

dedndave

well - to set a disk to read-only requires modification of the MBR
truthfully, that is a little bit outside the scope of the forum guidelines   :P

anyways - i don't think it can be done strictly with IOCTL
it is more of a COM task, transacted operations and all that stuff
or perhaps WMI - COM, again

MBRWizard lets you do all the stuff you need to do in command line switches
it also allows you to create and restore backup copies of the MBR
no need for the console-under-console stuff of DiskPart
another path might be PowerShell

attached is the 32-bit version
not sure how well it would work under win7 - i think they bumped the NTFS version to 6

dedndave

here we go
this may be a better alternative, as it is provided and supported by MS

Sector Inspector...

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=19470

colinr

At last I appear to have it working, I will share my findings of how I did it by modifying a code snippit that i came across!

Please excuse the lack of error checking but it is only test code.

.386
.model flat,stdcall
option casemap:none

include C:\masm32\include\windows.inc
include C:\masm32\include\masm32.inc
include C:\masm32\include\kernel32.inc
include C:\masm32\include\user32.inc
include C:\masm32\include\advapi32.inc

includelib C:\masm32\lib\kernel32.lib
includelib C:\masm32\lib\masm32.lib
includelib C:\masm32\lib\user32.lib
includelib C:\masm32\lib\advapi32.lib


.data
AppToSpawn  db "c:\windows\system32\diskpart.exe",0

ListDisk db "List Disk",0h
ExitDiskPart db "exit",0h


.data?
startinfo    STARTUPINFO <>
secat        SECURITY_ATTRIBUTES <>
secdes      SECURITY_DESCRIPTOR <>
procinfo    PROCESS_INFORMATION <>
newstdin    DWORD ?
newstout    DWORD ?
readout      DWORD ?
writein      DWORD ?
bytesRead    DWORD ?
bytesWrit    DWORD ?
avail        DWORD ?
buffer      db 1024 dup (?)

.code

start:
invoke InitializeSecurityDescriptor,addr secdes,SECURITY_DESCRIPTOR_REVISION
invoke SetSecurityDescriptorDacl,addr secdes,TRUE,NULL,FALSE

mov secat.lpSecurityDescriptor,offset secdes
mov secat.nLength,sizeof SECURITY_ATTRIBUTES
mov secat.bInheritHandle,TRUE

invoke CreatePipe,addr newstdin,addr writein,addr secat,0h ;Send Data
invoke CreatePipe,addr readout,addr newstout,addr secat,0h ;Receive Data

invoke GetStartupInfo,addr startinfo

mov startinfo.dwFlags,STARTF_USESTDHANDLES+STARTF_USESHOWWINDOW
mov startinfo.wShowWindow,SW_HIDE
mov eax,[newstout]
mov startinfo.hStdOutput,eax
mov startinfo.hStdError,eax
mov eax,[newstdin]
mov startinfo.hStdInput,eax

invoke CreateProcess,NULL,addr AppToSpawn,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,NULL,NULL,addr startinfo,addr procinfo

call ActivityDelayWithRead
                jnz short FatalError
                mov ecx, 10
                invoke WriteFile,writein,addr ListDisk,ecx,addr bytesWrit,NULL
               
                call ActivityDelayWithRead
                jnz short FatalError
               
                  mov ecx, 5
invoke WriteFile,writein,addr ExitDiskPart,ecx,addr bytesWrit,NULL

FatalError:
invoke CloseHandle,newstdin
invoke CloseHandle,writein
invoke CloseHandle,readout
invoke CloseHandle,newstout

invoke ExitProcess,0h

ActivityDelayWithRead:
mov esi,100 ;5 seconds delay overall, 100*5ms

ActivityLoop:
invoke Sleep,50 ;50 miliseconds
invoke RtlZeroMemory,addr buffer, 1024
invoke PeekNamedPipe,readout,addr buffer,1023,offset bytesRead,addr avail,NULL
                lea edi, buffer
                mov ecx, 1024 ;Let's search for 1024 btes
mov al, ">" ;We are looking for the greater than symbol
cld ;Clear direction
repne scasb
                je short FoundDiskPartPrompt
dec esi
jne short ActivityLoop
xor eax,eax
not eax
test eax, eax
ret

FoundDiskPartPrompt:
invoke ReadFile,readout,addr buffer,1023,addr bytesRead,NULL
xor eax, eax
test eax, eax
ret

end start