Last week we saw a PS4 API Demo from them, and today PlayStation 4 developers @kurt2467 and @BadChoicesZ are back with some more PS4 GTA V hax with full natives working... meaning any hacks that were possible on PS3 are now possible on Sony's PlayStation 4 console! 
Here's the latest Grand Theft Auto V PS4 video demo from kurt2467's YouTube channel with the caption below, to quote: [PS4] Some More GTA V Hax
I finally got all of the natives to work! This means that anything that was possible on PS3, is possible on PS4
PlayStation 4 GTAV Modding C# Code by Kurt2467 (Remote Procedure Calls)
From Pastebin.com: [PS4] GTA V RPC
From Pastebin.com: ArrayBuilder.cs
Thanks @raedoob and @GrimDoe for sharing the news in the PSXHAX Shoutbox! 
Here's the latest Grand Theft Auto V PS4 video demo from kurt2467's YouTube channel with the caption below, to quote: [PS4] Some More GTA V Hax
I finally got all of the natives to work! This means that anything that was possible on PS3, is possible on PS4
PlayStation 4 GTAV Modding C# Code by Kurt2467 (Remote Procedure Calls)
From Pastebin.com: [PS4] GTA V RPC
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PS4_GTA
{
public class RPC
{
private uint nativeArgBase = 0;
private uint hookAddress = 0;
private uint rpcCodeAddress = 0;
private List<uint> nativeFuncList = new List<uint>();
private List<UInt64> nativeHashList = new List<UInt64>();
public RPC()
{
nativeArgBase = 0x2DCD820;
hookAddress = 0xD8F480;
rpcCodeAddress = 0x5046D0;
}
public void InitRPC()
{
WriteU64(nativeArgBase, 0);
byte[] hook = new byte[] {
0x55, //push rbp
0xE8, 0x4A, 0x52, 0x77, 0xFF, //call 0x5046D0
0x5D, //pop rbp
0xC3, //retn
};
byte[] asmx86 = new byte[] {
0x55, //push rbp
0x41, 0x52, //push r10
0x53, //push rbx
0x49, 0xC7, 0xC2, 0x20, 0xD8, 0xDC, 0x02, //mov r10, 0x2DCD820
0x49, 0x8B, 0x1A, //mov rbx, [r10]
0x48, 0x85, 0xDB, //test rbx, rbx
0x74, 0x1A, //jz 0x5046FB
0x48, 0xC7, 0xC7, 0x30, 0xD8, 0xDC, 0x02, //mov rdi, 0x2DCD830
0xFF, 0xD3, //call rbx
0x49, 0xC7, 0xC2, 0x20, 0xD8, 0xDC, 0x02, //mov r10, 0x2DCD820
0x48, 0xC7, 0xC3, 0x00, 0x00, 0x00, 0x00, //mov rbx, 0
0x49, 0x89, 0x1A, //mov [r10], rbx
0x5B, //pop rbx
0x41, 0x5A, //pop r10
0x5D, //pop rbp
0xC3, //retn
};
SetMemory(rpcCodeAddress, asmx86);
SetMemory(hookAddress, hook);
WriteU64(nativeArgBase + 0x10, nativeArgBase + 0x50);
WriteU64(nativeArgBase + 0x20, nativeArgBase + 0x70);
}
public uint GetNativeAddress(UInt64 nativeHash)
{
uint nativeTable, index;
UInt64 nativeAddy;
nativeTable = 0x3644A28;
index = (uint)nativeHash & 0xFF;
nativeAddy = ReadU64(nativeTable + (index * 8));
while (nativeAddy != 0)
{
uint count = ReadU32(nativeAddy + 0x40);
for (uint i = 0; i < count; i++)
{
UInt64 hash = ReadU64(nativeAddy + 0x48 + (i * 8));
if (hash == nativeHash)
{
return ReadU32(nativeAddy + 0x8 + (i * 8));
}
}
nativeAddy = ReadU64(nativeAddy);
}
return 0;
}
public T CallRaw<T>(UInt64 address, params object[] args)
{
byte[] argBytes = new byte[0xA0];
ArrayBuilder ab = new ArrayBuilder(argBytes);
uint argStart = nativeArgBase + 0x70;
uint strStart = nativeArgBase + 0x120;
uint strCount = 0;
uint nativeArgCount = 0;
for (int i = 0; i < args.Length; i++)
{
if (args[i] is float)
{
ab.Write.SetFloat((int)nativeArgCount * 8, (float)args[i], ArrayBuilder.ArrayWriter.EndianType.LittleEndian);
nativeArgCount++;
}
else if (args[i] is string)
{
uint strPtr = (uint)strStart + (strCount * 0x20);
WriteString(strPtr, (string)args[i]);
ab.Write.SetUInt32((int)nativeArgCount * 8, strPtr, ArrayBuilder.ArrayWriter.EndianType.LittleEndian);
strCount++;
nativeArgCount++;
}
else if (args[i] is int)
{
ab.Write.SetInt32((int)nativeArgCount * 8, (int)args[i], ArrayBuilder.ArrayWriter.EndianType.LittleEndian);
nativeArgCount++;
}
else
{
UInt64 tmp = Convert.ToUInt64(args[i]);
ab.Write.SetUInt64((int)nativeArgCount * 8, tmp, ArrayBuilder.ArrayWriter.EndianType.LittleEndian);
nativeArgCount++;
}
}
SetMemory(argStart, argBytes);
System.Threading.Thread.Sleep(10);
WriteU64(nativeArgBase, (UInt64)address);
System.Threading.Thread.Sleep(30);
object ret = 0;
if (typeof(T).ToString() == "System.Int32")
{
ret = ReadI32(nativeArgBase + 0x50);
ret = (T)Convert.ChangeType(ret, typeof(T));
}
if (typeof(T).ToString() == "System.Int64")
{
ret = ReadI64(nativeArgBase + 0x50);
ret = (T)Convert.ChangeType(ret, typeof(T));
}
if (typeof(T).ToString() == "System.UInt32")
{
ret = ReadU32(nativeArgBase + 0x50);
ret = (T)Convert.ChangeType(ret, typeof(T));
}
if (typeof(T).ToString() == "System.UInt64")
{
ret = ReadU64(nativeArgBase + 0x50);
ret = (T)Convert.ChangeType(ret, typeof(T));
}
if (typeof(T).ToString() == "System.Single")
{
ret = ReadFloat(nativeArgBase + 0x50);
ret = (T)Convert.ChangeType(ret, typeof(T));
}
if (typeof(T).ToString() == "System.Single[]")
{
float[] fRet = new float[3];
fRet[0] = ReadFloat(nativeArgBase + 0x50);
fRet[1] = ReadFloat(nativeArgBase + 0x58);
fRet[2] = ReadFloat(nativeArgBase + 0x60);
ret = (T)Convert.ChangeType(fRet, typeof(T));
}
return (T)ret;
}
public T CallFunc<T>(UInt64 nativeAddress, params object[] args)
{
return CallRaw<T>(nativeAddress, args);
}
public T CallHash<T>(UInt64 nativeHash, params object[] args)
{
uint func;
if (nativeHashList.Contains((UInt64)nativeHash))
func = nativeFuncList[nativeHashList.IndexOf((UInt64)nativeHash)];
else
func = GetNativeAddress((UInt64)nativeHash);
if (func != 0)
{
nativeHashList.Add((UInt64)nativeHash);
nativeFuncList.Add(func);
return CallRaw<T>(func, args);
}
return (T)Convert.ChangeType(0, typeof(T));
}
}
}
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PS4_GTA
{
public class ArrayBuilder
{
private byte[] buffer;
private int size;
public ArrayWriter Write
{
get
{
return new ArrayWriter(this.buffer);
}
}
public ArrayBuilder(byte[] bytes)
{
this.buffer = bytes;
this.size = bytes.Length;
}
public class ArrayWriter
{
private byte[] buffer;
private int size;
public enum EndianType
{
LittleEndian,
BigEndian
};
public ArrayWriter(byte[] bytes)
{
this.buffer = bytes;
this.size = bytes.Length;
}
public void SetByte(int pos, byte value)
{
this.buffer[pos] = value;
}
public void SetInt32(int pos, int value, EndianType Type = EndianType.BigEndian)
{
byte[] bytes = BitConverter.GetBytes(value);
if (Type == EndianType.BigEndian)
Array.Reverse(bytes, 0, 4);
for (int i = 0; i < 4; i++)
this.buffer[i + pos] = bytes[i];
}
public void SetInt64(int pos, Int64 value, EndianType Type = EndianType.BigEndian)
{
byte[] bytes = BitConverter.GetBytes(value);
if (Type == EndianType.BigEndian)
Array.Reverse(bytes, 0, 8);
for (int i = 0; i < 8; i++)
this.buffer[i + pos] = bytes[i];
}
public void SetUInt32(int pos, uint value, EndianType Type = EndianType.BigEndian)
{
byte[] bytes = BitConverter.GetBytes(value);
if (Type == EndianType.BigEndian)
Array.Reverse(bytes, 0, 4);
for (int i = 0; i < 4; i++)
this.buffer[i + pos] = bytes[i];
}
public void SetUInt64(int pos, UInt64 value, EndianType Type = EndianType.BigEndian)
{
byte[] bytes = BitConverter.GetBytes(value);
if (Type == EndianType.BigEndian)
Array.Reverse(bytes, 0, 8);
for (int i = 0; i < 8; i++)
this.buffer[i + pos] = bytes[i];
}
public void SetBytes(int pos, byte[] value)
{
for (int i = 0; i < value.Length; i++)
this.buffer[i + pos] = value[i];
}
public void SetString(int pos, string str)
{
byte[] bytes = Encoding.UTF8.GetBytes(str + '\0');
for (int i = 0; i < bytes.Length; i++)
this.buffer[i + pos] = bytes[i];
}
public void SetFloat(int pos, float value, EndianType Type = EndianType.BigEndian)
{
byte[] bytes = BitConverter.GetBytes(value);
if (Type == EndianType.BigEndian)
Array.Reverse(bytes, 0, 4);
for (int i = 0; i < 4; i++)
this.buffer[i + pos] = bytes[i];
}
}
}
}