Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 192 Vote(s) - 3.48 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Loading programs to RAM and executing them NASM 16b

#1
I'm desperate for a solution to this. I'm trying to develop Assembly code allowing me to load and execute(by input of the user) 2 other Assembly .EXE programs. I'm having two problems:

- I don't seem to be able to assign the pathname to a valid register(Or maybe incorrect syntax)

- I need to be able to execute the other program after the first one (could be either) started its execution.

This is what I have so far:

mov ax,cs ; moving code segment to data segment
mov ds,ax

mov ah,1h ; here I read from keyboard
int 21h
mov dl,al

cmp al,'1' ; if 1 jump to LOADRUN1
JE LOADRUN1

cmp al,'2' ; if 2 jump to LOADRUN2
JE LOADRUN2

LOADRUN1:
MOV AH,4BH
MOV AL,00
LEA DX,[PROGNAME1] ; Not sure if it works
INT 21H


LOADRUN2:
MOV AH,4BH
MOV AL,00
LEA DX,[PROGNAME2] ; Not sure if it works
INT 21H

; Here I define the bytes containing the pathnames
PROGNAME1 db 'C:\Users\Usuario\NASM\Adding.exe',0
PROGNAME2 db 'C:\Users\Usuario\NASM\Substracting.exe',0
I just don't know how to start another program by input in the 'parent' program, after one is already executing.

Thanks in advance for your help! Any additional information I'll be more than happy to provide.

- Is not an overlay.
- I'm using NASM 16 bits, Windows 7 32 bits.
Reply

#2
According to [this reference][1], you are not setting the EXEC parameter block:

Format of EXEC parameter block for AL=00h,01h,04h:

Offset Size Description (Table 01590)
00h WORD segment of environment to copy for child process (copy caller's
environment if 0000h)
02h DWORD pointer to command tail to be copied into child's PSP
06h DWORD pointer to first FCB to be copied into child's PSP
0Ah DWORD pointer to second FCB to be copied into child's PSP
0Eh DWORD (AL=01h) will hold subprogram's initial SS:SP on return
12h DWORD (AL=01h) will hold entry point (CS:IP) on return

The referenced page lacks the `<pre>`/`</pre>` tags for this table, that's why it is hard to read in the page.

**You will have to set up such a parameter block and point ES:BX to it's address.**

----------

Is there any particular reason you are targetting 16 bit (DOS API) instead of the Win32 API? Assuming you can get away with targetting the Win32 API instead, you can start external executables using the [WinExec][2] call in something like this skeleton:

global _WinMain@16

; WinExec(char *lpCmdLine, int uCmdShow)
extern _WinExec@8

[section .code]
_WinMain@16:
; ... read input and jump to loadrun1 or loadrun2 here

loadrun1:
push dword 1
push dword progname1
call _WinExec@8
ret

loadrun2:
push dword 1
push dword progname2
call _WinExec@8
ret

[section .data]
progname1 db 'C:\Users\Usuario\NASM\Adding.exe',0
progname2 db 'C:\Users\Usuario\NASM\Substracting.exe',0

Alternatively, you can use the more modern [ShellExecute][3] call.

[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply

#3
After some hacking and twiddling, I was able to get this working. It's not as straightforward as I hoped it would be, so hold on to your seat(s).

Firstly, you need to realize (as abstract as that may sound) that DOS is a single-user, non-multitasking system. In this particular case, it means that you can't have two processes running concurrently. You **need** to wait for one process to finish execution before moving to another process. Process concurrency may be somewhat emulated with TSR (Terminate and Stay Resident) processes, which stay in memory despite being terminated and it's possible to resume their execution by hooking some interrupts from their code and calling it from some other code later on. Still, it's not the same kind of concurrency that's used by modern OSes, like Windows and Linux. But that wasn't the point.

You said that you're using NASM as your assembler of choice, therefore I assumed that you output your code to COM files, which are in turn executed by the DOS command prompt. COM files are loaded by the command prompt at offset `100h` (after loading a jump to that location is executed) and don't contain anything else but "lean" code and data - no headers, thus they're the easiest to produce.

I'm going to explain the assembly source in pieces, so that you can (perhaps) get a better glimpse of what's going on under the hood.

The program begins with

org 100h

section .data
exename db "C:\hello.com",0
exename2 db "C:\nasm\nasm.exe",0
cmdline db 0,0dh

the `org` directive, which specifies the origin of the file when actually loaded into memory - in our case, this is `100h`. Declarations of three labels follow, `exename` and `exename2` which are null-terminated paths of the programs to execute, and `cmdline`, which specifies the command line that the newly created process should receive. Note that it isn't just a normal string : the first byte is the number of characters in the commandline, then the commandline itself, and a Carriage Return. In this case, we have no commandline parameters, so the whole thing boils down to `db 0,0dh`. Suppose we wanted to pass `-h -x 3` as the params : in that case, we'd need to declare this label as `db 8," -h -x 3",0dh` (note the extra space at the beginning!). Moving on...

dummy times 20 db 0

paramblock dw 0
dw cmdline
dw 0 ; cmdline_seg
dw dummy ; fcb1
dw 0 ; fcb1_seg
dw dummy ; fcb2
dw 0 ; fcb2_seg

The label `dummy` is just 20 bytes which contain zeroes. What follows is the `paramblock` label, which is a representation of the EXEC structure mentioned by Daniel Roethlisberger. The first item is a zero, which means that the new process should have the same environment as its parent. Three addresses follow : to the commandline, to the first FCB, and the second FCB. You should remember that addresses in real mode consist of two parts : the address of the segment and the offset into the segment. Both those addresses are 16 bits long. They're written in the memory in little endian fashion, with the offset being first. Therefore, we specify the commandline as offset `cmdline`, and addresses of the FCBs as offsets to the label `dummy`, since the FCBs themselves are not going to be used but the addresses need to point to a valid memory location either way. The segments need to be filled at runtime, since the loader chooses the segment at which the COM file is loaded.

section .text
entry:
mov ax, cs
mov [paramblock+4], ax
mov [paramblock+8], ax
mov [paramblock+12],ax

We begin the program by setting the segment fields in the `paramblock` structure. Since for COM files, `CS = DS = ES = SS`, i.e. all the segments are the same, we just set those values to what's in the `cs` register.

mov ax, 4a00h
mov bx, 50
int 21h

This is actually one of the trickiest points of the application. When a COM file is loaded into the memory by DOS, it is assigned all the available memory by default (the CPU has no idea about this, since it's in real mode, but DOS internals keep track of it anyway). Therefore, calling the EXEC syscall causes it to fail with `No memory available`. Therefore, we need to tell DOS that we don't really need all that memory by executing the "RESIZE MEMORY BLOCK" `AH=4Ah` call [(Ralf Brown)][1]. The `bx` register is supposed to have the new size of the memory block in 16-byte units ("paragraphs"), so we set it to 50, having 800 bytes for our program. I have to admit that this value was chosen randomly, I tried setting it to something which would make sense (e.g. a value based on the actual file size), but I kept getting nowhere. `ES` is the segment that we want to "resize", in our case that's `CS` (or any other one, since they're all the same when a COM file is loaded). After completing this call, we're ready to load our new program to memory and execute it.

mov ax, 0100h
int 21h
cmp al, '1'
je .prog1
cmp al, '2'
je .prog2
jmp .end

.prog1:
mov dx, exename
jmp .exec

.prog2:
mov dx, exename2

This code should be pretty self-explanatory, it chooses the path to the program inserted into `DX` based on the stdin.

.exec:
mov bx, paramblock
mov ax, 4b00h
int 21h

This is where the actual `EXEC` syscall (`AH=4Bh`) is called. `AL` contains 0, which means that the program should be loaded and executed. `DS:DX` contains the address of the path to the executable (chosen by the earlier piece of code), and `ES:BX` contains the address of the `paramblock` label, which contains the `EXEC` structure.

.end:
mov ax, 4c00h
int 21h

After finishing the execution of the program called by `exec`, the parent program is terminated with an exit code of zero by executing the `AH=4Ch` syscall.

Thanks to `vulture-` from ##asm on Freenode for help. I tested this with DOSBox and MS-DOS 6.22, so hopefully it works for you as well.

[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through