Why do neither trace-msr nor break-msr show changes to msr_ia32_smbase in Simics? - simics

I tried multiple ways to break on the write to smbase. First I tried
board.mb.cpu0.core[0][0].break-msr 0x9E
But when I run, it just runs forever without breaking.
Then I tried to break in SMM, and then just trace its access, but this showed no hits.
simics> break-hap X86_Leave_SMM
simics> break-hap X86_Enter_SMM
simics> r
[board.mb.sb.lpc.bank.cs_conf unimpl] Write to unimplemented field cs_conf.oic.aen (0x31ff) (value written = 0x01, contents = 0x00), will not warn again.
[board.mb.cpu0.core[1][0] trace-hap] X86_Enter_SMM 0
[board.mb.cpu0.core[1][0] trace-hap] X86_Enter_SMM 1
break-hap
break-hap
simics> board.mb.cpu0.core[0][0].trace-msr -all
simics> r
[board.mb.cpu0.core[1][0] trace-hap] X86_Leave_SMM 0
[board.mb.cpu0.core[1][0] trace-hap] X86_Leave_SMM 1
Setting new inspection object: board.mb.cpu0.core[1][0]
break-hap
break-hap
Then I thought maybe the SMM exit break was obscuring the write, so I tried setting a break on SMM entry, and then breaking on all MSR writes and letting it continue. But it showed no breaks until the next entry to SMM.
simics> break-hap X86_Enter_SMM
simics> r
[board.mb.sb.lpc.bank.cs_conf unimpl] Write to unimplemented field cs_conf.oic.aen (0x31ff) (value written = 0x01, contents = 0x00), will not warn again.
[board.mb.cpu0.core[1][0] trace-hap] X86_Enter_SMM 0
[board.mb.cpu0.core[1][0] trace-hap] X86_Enter_SMM 1
break-hap
break-hap
simics> board.mb.cpu0.core[0][0].break-msr -all
simics> r
[board.mb.cpu0.core[2][0] trace-hap] X86_Enter_SMM 0
[board.mb.cpu0.core[2][0] trace-hap] X86_Enter_SMM 1
break-hap
break-hap
So in the below you can see concretely that msr_ia32_smbase is definitely getting written after the first exit of SMM. But none of the trace or break capabilities seem to show that, even when run from within SMM. So is this just not supported functionality?
simics> board.mb.cpu0.core[0][0].trace-msr 0x9E
simics> board.mb.cpu0.core[0][0].trace-msr -list
[board.mb.cpu0.core[0][0]] Tracing enabled for these control registers:
msr_ia32_smbase
simics> board.mb.cpu0.core[0][0].break-msr 0x9E
simics> board.mb.cpu0.core[0][0].break-msr -list
[board.mb.cpu0.core[0][0]] Breaking enabled for these control registers:
msr_ia32_smbase
simics> break-hap X86_Enter_SMM
simics> break-hap X86_Leave_SMM
simics> print -x %msr_ia32_smbase
0x30000
simics> r
[board.mb.sb.lpc.bank.cs_conf unimpl] Write to unimplemented field cs_conf.oic.aen (0x31ff) (value written = 0x01, contents = 0x00), will not warn again.
[board.mb.cpu0.core[1][0] trace-hap] X86_Enter_SMM 0
[board.mb.cpu0.core[1][0] trace-hap] X86_Enter_SMM 1
break-hap
break-hap
simics> print -x %msr_ia32_smbase
0x30000
simics> r
[board.mb.cpu0.core[1][0] trace-hap] X86_Leave_SMM 0
[board.mb.cpu0.core[1][0] trace-hap] X86_Leave_SMM 1
Setting new inspection object: board.mb.cpu0.core[1][0]
break-hap
break-hap
simics> print -x %msr_ia32_smbase
0xdffcf000
p.s. I think the help for break-msr has a copy-paste error, as it says "The register parameter specifies which segment register should be traced." The trace-msr correctly says model specific register.

IA32_SMBASE MSR is a read-only MSR, you can check Intel Software Development Manual to find this information.
trace-msr only traces write accesses to the register done by WRMSR instruction, i.e. neither internal flows nor attribute/interfaces accesses will be traced by this command.
Likely, in your case SMBASE is updated as part of RSM flow, you can check "SMBASE relocation" section in SDM for more details. Thus you don't get any messages from trace-msr command.
Another thing that I can notice from the small pieces of logs in you question: you enabled trace-msr and break-msr only on core[0][0] while you observing smbase changes on core[1][0]. Look at this message: "Setting new inspection object: board.mb.cpu0.core[1][0]".
And thanks for the note about the copy-paste error. I will fix it.

Related

How to set an exception using masm64?

How can i access the exception chain (SEH) using masm64?
Using masm32, I get the first exception looking into fs:[0]
But when I checked in Windbg if fs:[0] still pointed at the first exception in x64, I figured that it wasn't.
I'd like to set an exception in x64 the same way I did in x86. Is it feasible (maybe looking at gs register)?
If this is coding related then you use
ml64seh PROC FRAME:ExceptionFilter
this adds your exception handler to .PDATA section RUNTIME_FUNCTION
if this is how to find this exception handler in windbg when the exception has been raised
use !exchain command
or if you want to find it before executing a specific function use .fnent command
a sample for x64 seh and finding it in windbg is as follows
;assemble and link with
;ml64 /Zi ml64seh.asm /link /debug /entry:ml64seh /subsystem:console
.data
safeplace DWORD ?
.code
ExceptionFilter PROC
jmp Handler
ExceptionFilter ENDP
PUBLIC ml64seh
ml64seh PROC FRAME:ExceptionFilter
.ENDPROLOG
mov rax, 0
mov [rax], rax ;access violation
jmp exit
Handler::
lea rax, safeplace
mov [r8+078h], rax ; replacing rax in exception handler so access is possible
mov rax, 0
ret
Exit:
ret
ml64seh ENDP
END
run without stopping in windbg
:\>cdb -g ml64seh.exe
(2aa0.3024): Access violation - code c0000005 (first chance)
ml64seh!ml64seh+0x7:
00007ff7`0e3b1029 488900 mov qword ptr [rax],rax ds:00000000`00000000=????????????????
0:000>
it crashed and broke now locating exception handlers
0:000> .fnent .
Debugger function entry 0000020b`e36c47a8 for:
(00007ff7`0e3b1022) ml64seh!ml64seh+0x7 | (00007ff7`0e3b32b0) ml64seh!$xdatasym
BeginAddress = 00000000`00001022
EndAddress = 00000000`00001042
UnwindInfoAddress = 00000000`000032b0
Unwind info at 00007ff7`0e3b32b0, c bytes
version 1, flags 3, prolog 0, codes 0
handler routine: ml64seh!ILT+0(ExceptionFilter) (00007ff7`0e3b1005), data 0 <<<<<<<<<
0:000> !exchain
3 stack frames, scanning for handlers...
Frame 0x00: ml64seh!ml64seh+0x7 (00007ff7`0e3b1029)
ehandler ml64seh!ILT+0(ExceptionFilter) (00007ff7`0e3b1005) <<<<<<<<<<<<
Frame 0x02: ntdll!RtlUserThreadStart+0x21 (00007ffe`213c26a1)
ehandler ntdll!_C_specific_handler (00007ffe`213fc720)
0:000>
lets see if we go to the handler and return back to re access the faulting place
0:000> bp .
0:000> bp 00007ff7`0e3b1005
0:000> bl
0 e 00007ff7`0e3b1029 0001 (0001) 0:**** ml64seh!ml64seh+0x7
1 e 00007ff7`0e3b1005 0001 (0001) 0:**** ml64seh!ILT+0(ExceptionFilter)
0:000> g
Breakpoint 1 hit
ml64seh!ILT+0(ExceptionFilter):
00007ff7`0e3b1005 e916000000 jmp ml64seh!ExceptionFilter (00007ff7`0e3b1020)
0:000> g
Breakpoint 0 hit
ml64seh!ml64seh+0x7: is accessible now
00007ff7`0e3b1029 488900 mov qword ptr [rax],rax ds:00007ff7`0e3b4000=0000000000000000
0:000>
btw you can use dumpbin or linker to spit out all the unwindinfos in a specific binary using -unwindinfo switch
:\>dumpbin /unwindinfo ml64seh.exe
Microsoft (R) COFF/PE Dumper Version 14.29.30146.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file ml64seh.exe
File Type: EXECUTABLE IMAGE
Function Table (1)
Begin End Info Function Name
00000000 00001022 00001042 000032B0 ml64seh
Unwind version: 1
Unwind flags: EHANDLER UHANDLER
Size of prologue: 0x00
Count of codes: 0
Handler: 00001005 #ILT+0(ExceptionFilter)

Radare2 "pd" command

I am currently using Radare2 to extract opcodes from PE files. Currently, I am attempting to use the "pd" command which from the API: "pd n # offset: Print n opcodes disassembled". I am wondering if there is a way to calculate/find out exactly what "n" is for each file I process. Thanks
ENVIRONMENT
radare2: radare2 4.2.0-git 23519 # linux-x86-64 git.4.1.1-84-g0c46c3e1e commit: 0c46c3e1e30bb272a5a05fc367d874af32b41fe4 build: 2020-01-08__09:49:0
system: Ubuntu 18.04.3 LTS
SOLUTION
This example shows 4 different options to view / print disassembly or opcodes.
View disassembly in radare2 via visual mode:
Command one: aaaa # Analyze the file
Command two: Vp # Open disassembly in visual mode
Print disassembly of all functions in r2 or r2pipe:
Command one: aaaa # Analyze the file
Command two: pdf ##f > out
pdf # Print disassembly of a function
##f # Repeat the command for every function
> out # Redirect the output to the file named out
Print only the instruction in r2 or r2pipe:
Command one: aaaa # Analyze the file
Command two: pif ##f ~[0] > out
pif # Print instructions of a function
##f # Repeat the command for every function
~[0] # Only print the first column (The instruction)
> out # Redirect the output to the file named out
Obtained detailed information for each opcode using r2 or r2pipe:
Command one: aaaa # Analyzey the file
Command two: aoj ##=`pid ##f ~[0]` > out
aoj # Display opcode analysis information in JSON
##= # Repeat the command for every offset return by sub-query
pid ##f ~[0] # The sub-query
pid # Print disassembly with offset and bytes
##f # Repeat the command for every function
~[0] # Only print the first column (The offset)
> out # Redirect the output to the file named out
EXAMPLE
Replace the commands here with any option from above.
Example using radare2 shell
user#host:~$ r2 /bin/ls
[0x00005850]> aaaa
...
[0x00005850]> pdf ##f > out
[0x00005850]> q
user#host:~$ cat out
...
┌ 38: fcn.00014840 ();
│ ; var int64_t var_38h # rsp+0xffffffd0
│ 0x00014840 53 push rbx
│ 0x00014841 31f6 xor esi, esi
│ 0x00014843 31ff xor edi, edi
│ 0x00014845 e846f2feff call sym.imp.getcwd
│ 0x0001484a 4885c0 test rax, rax
│ 0x0001484d 4889c3 mov rbx, rax
│ ┌─< 0x00014850 740e je 0x14860
│ │ ; CODE XREF from fcn.00014840 # 0x14868
│ ┌──> 0x00014852 4889d8 mov rax, rbx
│ ╎│ 0x00014855 5b pop rbx
│ ╎│ 0x00014856 c3 ret
..
│ ╎│ ; CODE XREF from fcn.00014840 # 0x14850
│ ╎└─> 0x00014860 e88beffeff call sym.imp.__errno_location
│ ╎ 0x00014865 83380c cmp dword [rax], 0xc
│ └──< 0x00014868 75e8 jne 0x14852
└ 0x0001486a e861feffff call fcn.000146d0
; CALL XREFS from fcn.00013d00 # 0x13d9d, 0x13da8
...
Example using Python with r2pipe
import r2pipe
R2 = r2pipe.open('/bin/ls') # Open r2 with file
R2.cmd('aaaa') # Analyze file
R2.cmd('pdf ##f > out') # Write disassembly for each function to out file
R2.quit() # Quit r2

DBX showing incorrect values in shared library built with -g

-bash-3.2$ uname -a
SunOS b2s-sol10spr-1 5.10 Generic_147147-26 sun4v sparc sun4v
-bash-3.2$ dbx -V
Sun DBX Debugger 8.0 SunOS_sparc 2014/10/21
For information about new features see `help changes'
To remove this message, put `dbxenv suppress_startup_message 8.0' in your .dbxrc
(dbx)
I'm getting a weird issue where the debugger is just showing completely wrong values for function parameters & local/member variables.
Here's a sample backtrace
=>[1] SQLGetDiagRecW(HandleType = -28417, Handle = 0x480000000101dfc1, RecNumber = -12288, Sqlstate = (nil), NativeError = 0xffffffff7fffdf, MessageText = 0x9100000001002bbd, BufferLength = -9583, TextLength = 0x380000000101da91), line 3154 in "CInterface.cpp"
[2] extract_diag_error_w(htype = 3, handle = 0x3, connection = 0x1014d32c0, head = 0x101e5a5e0, return_code = -1, save_to_diag = 0), line 4447 in "__info.c"
[3] function_return_ex(level = 3, handle = 0x101e5a1a0, ret_code = -1, save_to_diag = 0), line 4863 in "__info.c"
[4] SQLExecDirectW(statement_handle = 0x101e5a1a0, statement_text = 0x101dacde0, text_length = -3), line 442 in "SQLExecDirectW.c"
<truncated>
Frame 1 is in the problematic shared library, while the other frames are in the unixODBC libodbc.so
If we look at the code for extract_diag_error_w (you can get the code from http://www.unixodbc.org/unixODBC-2.3.1.tar.gz, the following snippet is from DriverManager/__info.c )
ret = SQLGETDIAGRECW( connection,
head -> handle_type,
handle,
rec_number,
sqlstate,
&native,
msg1,
sizeof( msg1 ),
&len );
Note that we have, elsewhere
#define SQLGETDIAGRECW(con,typ,han,rn,st,nat,msg,bl,tlp)\
(con->functions[77].funcW)\
(typ,han,rn,st,nat,msg,bl,tlp)
in dbx, if I go to frame 2 and print head -> handle_type, I get 3, but if I go to frame 1 and print HandleType, I get -28417.
I'd expect dbx, if it can't find the value (due to optimization or w/e, even though this was a debug build), to tell me so (<value optimized out> or somesuch). Also, every value I look at seems to be wrong (I've confirmed that the debugger is lying to me via control flow, there's code like if (x < 0) throw ...; where dbx claims it's some negative number, but the exception doesn't get thrown.
The problematic shared libary was built on another machine (while unixODBC was built locally), so maybe that's involved? It was also built w/ gcc, where I used the default compiler when building unixODBC (though I think it's also w/ gcc, since they both have a dependency on libgcc_s.so.1)
Any suggestions? (I'd guess updating dbx might work, but it would be difficult in this environment).
edit: Here's an example w/ local variables
(dbx) next
t#1 (l#1) stopped in Simba::Support::ODBCStringConverter::ConvertWStringToSQLWCHARString at line 64 in file "ODBCStringConverter.cpp"
64 simba_int32 length = in_length;
(dbx) next
t#1 (l#1) stopped in Simba::Support::ODBCStringConverter::ConvertWStringToSQLWCHARString at line 66 in file "ODBCStringConverter.cpp"
66 if (0 == in_length)
(dbx) print length
length = 11
(dbx) print in_length
in_length = 419430399
(dbx) next
t#1 (l#1) stopped in Simba::Support::ODBCStringConverter::ConvertWStringToSQLWCHARString at line 73 in file "ODBCStringConverter.cpp"
73 else if (SIMBA_NTS == in_length)
(dbx) next
t#1 (l#1) stopped in Simba::Support::ODBCStringConverter::ConvertWStringToSQLWCHARString at line 79 in file "ODBCStringConverter.cpp"
79 simba_int32 bufferBytes = length;
(dbx) next
t#1 (l#1) stopped in Simba::Support::ODBCStringConverter::ConvertWStringToSQLWCHARString at line 80 in file "ODBCStringConverter.cpp"
80 if (!in_isLengthInBytes)
(dbx) print bufferBytes
bufferBytes = 1744830464
(dbx)
edit 2: Here's how the troublesome library was built (need to rebuild unixODBC, will do that later).
Example command for compiling one of the .cpp files (I removed a bunch of include directories)
/opt/csw/gcc4/bin/g++ -DSIZEOF_LONG_INT=8 -DSQL_WCHART_CONVERT -DHAVE_MEMMOVE -m64 -fPIC -pthread -Wall -Wno-unknown-pragmas -DSIMBA -D_REENTRANT -DCLUNIX -DNDEBUG -D_POSIX_PTHREAD_SEMANTICS -O0 -g -D_DEBUG -c Common/QSTableMetadataFile.cpp -o Common/QSTableMetadataFile_solaris10sparc_gcc4_9_debug64.cpp.o
Command used to link (removed a bunch of .o files)
/opt/csw/gcc4/bin/g++ -DSIMBA -D_REENTRANT -m64 -fPIC -pthread -Wall -Wno-unknown-pragmas -lrt -O0 -g -shared -L/bamboo/bamboo-agent-home/xml-data/build-dir/ThirdParty/icu/53.1.x/solaris10sparc/gcc4_9/release64/lib -lstdc++ -licudata_sb64 -licui18n_sb64 -licuuc_sb64 -lpthread -lm -lsocket -lnsl -Wl,-M,exports_SunOS.map -Wl,-zallextract,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libSimbaDSI.a,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libSimbaSupport.a,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libAEProcessor.a,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libCore.a,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libDSIExt.a,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libExecutor.a,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libParser.a,/bamboo/bamboo-agent-home/xml-data/build-dir/SimbaEngine/Maintenance/10.1/Product/Lib/solaris10sparc/gcc4_9/debug64/libSimbaODBC.a -Wl,-zweakextract -o ../Bin/solaris10sparc/gcc4_9/debug64/libQuickstart64.so

Getting Symbols from crashes at Microsoft Dev Dashboard

The Microsoft Windows Dev Center Dashboard lets me collect stack traces from failures in my native desktop app in the wild.
Unfortunately, minidumps aren't avaialble. I just get a TSV file that (sometimes) has a stack trace in it, which looks like this:
Frame Image Function Offset
0 MyApp 0x2F59A1
1 MyApp 0x11CEA8
2 MyApp 0x11AE74
3 MyApp 0x151289
4 MyApp 0x2A686
5 MyApp 0x180720
6 MyApp 0x1807B6
7 MyApp 0x2E875A
8 MyApp 0x2E8882
9 kernel32 BaseThreadInitThunk 0x24
10 ntdll __RtlUserThreadStart 0x2B
11 ntdll _RtlUserThreadStart 0x1B
To make this uesful, I load the matching binary in WinDbg, figure out the offset plus the base address, and unassemble at the resulting address. If my app loads at 0x00400000, I add 0x2F59A1 to it and get 0x006F59A1. Unassembling there shows me the return address of that stack frame, so I can get some idea of what the crash is about.
Is there a better way? How can I request minidumps from Dev Center? (Microsoft Support says I just can't. Really?) Is there a script to convert at TSV file a usable stack trace so I don't manually evaluate each stack frame? Is there some other way?
I don't know if you can get a .dmp or not google says you can not get one from dash board
the answer below is a modified version of a script
I once used it to disassemble # .map file offsets improvise if needed
it takes the offsets from the column using pandas
creates a command string and uses subprocess to disassemble at that offset
i assume the tsv is a tab seperated value file if not you have some tweaking to do
assuming tab seperated file with data like below
Frame Image Function Offset
0 calc 0x1012
0 calc 0x1015
you can automate the process with some for loops in the code below
edit since i do two subprocess calls the offsets for both forward and backward disassembly are different (ASLR effect )
:\>cat Untitled.py
import pandas as pd
df = pd.read_csv("tsv.txt" , delimiter='\t')
print df
offset = df.Function.unique()[1]
print offset
import subprocess
cmdline = "cdb -c \"ub calc+"+offset+";q\" calc.exe | tail"
print cmdline
output = subprocess.check_output(cmdline ,shell=True )
print output
cmdline = "cdb -c \"u calc+"+offset+";q\" calc.exe | tail"
print cmdline
output = subprocess.check_output(cmdline ,shell=True )
print output
:\>python Untitled.py
Frame Image Function Offset
0 0 calc 0x1012 NaN
1 0 calc 0x1015 NaN
0x1015
cdb -c "ub calc+0x1015;q" calc.exe | tail
calc!_imp__SHGetFolderPathW+0x1:
00f31005 57 push edi
00f31006 1f pop ds
00f31007 7629 jbe calc!_imp__GdipCloneImage+0x2 (00f31032)
00f31009 a1237683dd mov eax,dword ptr ds:[DD837623h]
00f3100e 27 daa
00f3100f 7646 jbe calc!_imp__GdipDeleteGraphics+0x3 (00f31057)
00f31011 1e push ds
00f31012 197600 sbb dword ptr [esi],esi
quit:
cdb -c "u calc+0x1015;q" calc.exe | tail
calc!⌂SHELL32_NULL_THUNK_DATA+0x1:
009b1015 0000 add byte ptr [eax],al
009b1017 007a41 add byte ptr [edx+41h],bh
009b101a 5f pop edi
009b101b 7700 ja calc!⌂SHLWAPI_NULL_THUNK_DATA+0x1 (009b101d)
009b101d 0000 add byte ptr [eax],al
009b101f 005fa1 add byte ptr [edi-5Fh],bl
009b1022 687449a568 push 68A54974h
009b1027 744a je calc!_imp__GdiplusShutdown+0x3 (009b1073)
quit:
:\>

Segfault when running hello world shellcode in C program

sorry if this question sounds dumb but I am very new to shellcoding and I was trying to get a hello world example to work on a 32 bit linux machine.
As this is shellcoding, I used a few tricks to remove null bytes and shorten the code. Here it is:
section .data
section .text
global _start
_start:
;Instead of xor eax,eax
;mov al,0x4
push byte 0x4
pop eax
;xor ebx,ebx
push byte 0x1
pop ebx
;xor ecx,ecx
cdq ; instead of xor edx,edx
;mov al, 0x4
;mov bl, 0x1
mov dl, 0x8
push 0x65726568
push 0x74206948
;mov ecx, esp
push esp
pop ecx
int 0x80
mov al, 0x1
xor ebx,ebx
int 0x80
This code works fine when I compile and link it with the following commands:
$ nasm -f elf print4.asm
$ ld -o print4 -m elf_i386 print4.o
However, I tried running it within the following C code:
$ cat shellcodetest.c
#include
#include
char *shellcode = "\x04\x6a\x58\x66\x01\x6a\x5b\x66\x99\x66\x08\xb2\x68\x68\x68\x65\x69\x48\x54\x66\x59\x66\x80\xcd\x01\xb0\x31\x66\xcd\xdb\x80";
int main(void) {
( *( void(*)() ) shellcode)();
}
$ gcc shellcodetest.c –m32 –z execstack -o shellcodetest
$ ./shellcodetest
Segmentation fault (core dumped)
Could someone please explain what is happening there? I tried running the code in gdb and noticed something weird happening with esp. But as I said before, I still lack experience to really understand what is going on here.
Thanks in advance!
Your shellcode does not work, because it is not entered in the correct endianness. You did not state how you extracted the bytes from the file print4, but both objdump and xxd gives the bytes in correct order.
$ xxd print4 | grep -A1 here
0000060: 6a04 586a 015b 99b2 0868 6865 7265 6848 j.Xj.[...hherehH
0000070: 6920 7454 59cd 80b0 0131 dbcd 8000 2e73 i tTY....1.....s
$ objdump -d print4
print4: file format elf32-i386
Disassembly of section .text:
08048060 <_start>:
8048060: 6a 04 push $0x4
8048062: 58 pop %eax
8048063: 6a 01 push $0x1
...
The changes you need to do is to swap the byte order, '\x04\x6a' -> '\x6a\x04'.
When I run your code with this change, it works!
$ cat shellcodetest.c
char *shellcode = "\x6a\x04\x58\x6a\x01\x5b\x99\xb2\x08\x68\x68\x65\x72\x65\x68\x48\x69\x20\x74\x54\x59\xcd\x80\xb0\x01\x31\xdb\xcd\x80";
int main(void) {
( *( void(*)() ) shellcode)();
}
$ gcc shellcodetest.c -m32 -z execstack -o shellcodetest
$ ./shellcodetest
Hi there$