Skip to content

Instantly share code, notes, and snippets.

@19h
Last active November 10, 2025 05:30
Show Gist options
  • Select an option

  • Save 19h/e0c6e57bc097d561ad777d7524cb9b7f to your computer and use it in GitHub Desktop.

Select an option

Save 19h/e0c6e57bc097d561ad777d7524cb9b7f to your computer and use it in GitHub Desktop.
Gemini - CodeDump - PTN test
// Decompiled code dump generated by CodeDumper
// --------
#PTN v0
// @PTN LEGEND
// Nodes: L(F,i)=local i in function F; P(F,i)=param i of F; G(addr)=global at addr; F(Fx)=function Fx.
// Slices: @[off:len] in bytes; '?' unknown; '&' = address-of; '*' = deref; optional cast as :(type).
// A: alias inside function => A: dst := src[@slice][mode][:cast] {meta}
// I: inbound (caller→this) => I: origin -> P(F,i) {caller=F?,cs=0x...,conf=...}
// E: outbound (this→callee) => E: origin -> A(F?,arg) [-> A(F?,arg)...] {cs=0x...,conf=...}
// G: global touch/summary => G: F(F?) -> G(0xADDR) or G: F(writer) -> G(0xADDR) -> F(reader)
// Dictionary entry (per function block): // @PTN D:F?=0xEA,Name
// --------
// Start Function: 0x154D (main)
// Caller Depth: 3
// Callee/Ref Depth: 3
// Total Functions Found: 19
// Included Functions (19):
// - strncpy (0x4028)
// - puts (0x4030)
// - strlen (0x4038)
// - __stack_chk_fail (0x4040)
// - printf (0x4048)
// - strcat (0x4050)
// - .strncpy (0x10A0)
// - .puts (0x10B0)
// - .strlen (0x10C0)
// - .__stack_chk_fail (0x10D0)
// - .printf (0x10E0)
// - .strcat (0x10F0)
// - leaf_function_a (0x12A4)
// - leaf_function_b (0x1304)
// - create_untrusted_data (0x11E9)
// - process_result (0x14E6)
// - another_intermediate (0x141A)
// - intermediate_function (0x1353)
// - main (0x154D)
// Removed Functions: None
// ------------------------------------------------------------
// Incoming xrefs for strncpy (0x4028): .strncpy (0x10A0) [direct_call]
// Outgoing xrefs for strncpy (0x4028): None
// @PTN D:F14=0x4028,strncpy
// @PTN I:L(F1,0)@[?:0x8] {conf=high,cs=0x10A4,caller=F1} -> P(F14,0)
// @PTN I:L(F1,1)@[?:0x8] {conf=high,cs=0x10A4,caller=F1} -> P(F14,1)
// @PTN I:L(F1,2)@[?:0x8] {conf=high,cs=0x10A4,caller=F1} -> P(F14,2)
// --- Function: strncpy (0x4028) ---
// Decompilation FAILED for strncpy (0x4028) - Decompiler returned None
// --- End Function: strncpy (0x4028) ---
// Incoming xrefs for puts (0x4030): .puts (0x10B0) [direct_call]
// Outgoing xrefs for puts (0x4030): None
// @PTN D:F15=0x4030,puts
// @PTN I:L(F2,0)@[?:0x8] {conf=high,cs=0x10B4,caller=F2} -> P(F15,0)
// --- Function: puts (0x4030) ---
// Decompilation FAILED for puts (0x4030) - Decompiler returned None
// --- End Function: puts (0x4030) ---
// Incoming xrefs for strlen (0x4038): .strlen (0x10C0) [direct_call]
// Outgoing xrefs for strlen (0x4038): None
// @PTN D:F16=0x4038,strlen
// @PTN I:L(F3,0)@[?:0x8] {conf=high,cs=0x10C4,caller=F3} -> P(F16,0)
// --- Function: strlen (0x4038) ---
// Decompilation FAILED for strlen (0x4038) - Decompiler returned None
// --- End Function: strlen (0x4038) ---
// Incoming xrefs for __stack_chk_fail (0x4040): .__stack_chk_fail (0x10D0) [direct_call]
// Outgoing xrefs for __stack_chk_fail (0x4040): None
// @PTN D:F17=0x4040,__stack_chk_fail
// --- Function: __stack_chk_fail (0x4040) ---
// Decompilation FAILED for __stack_chk_fail (0x4040) - Decompiler returned None
// --- End Function: __stack_chk_fail (0x4040) ---
// Incoming xrefs for printf (0x4048): .printf (0x10E0) [direct_call]
// Outgoing xrefs for printf (0x4048): None
// @PTN D:F18=0x4048,printf
// @PTN I:L(F5,0)@[?:0x8] {conf=high,cs=0x10E4,caller=F5} -> P(F18,0)
// --- Function: printf (0x4048) ---
// Decompilation FAILED for printf (0x4048) - Decompiler returned None
// --- End Function: printf (0x4048) ---
// Incoming xrefs for strcat (0x4050): .strcat (0x10F0) [direct_call]
// Outgoing xrefs for strcat (0x4050): None
// @PTN D:F19=0x4050,strcat
// @PTN I:L(F6,0)@[?:0x8] {conf=high,cs=0x10F4,caller=F6} -> P(F19,0)
// @PTN I:L(F6,1)@[?:0x8] {conf=high,cs=0x10F4,caller=F6} -> P(F19,1)
// --- Function: strcat (0x4050) ---
// Decompilation FAILED for strcat (0x4050) - Decompiler returned None
// --- End Function: strcat (0x4050) ---
// Incoming xrefs for .strncpy (0x10A0): create_untrusted_data (0x11E9) [direct_call]
// Outgoing xrefs for .strncpy (0x10A0): strncpy (0x4028) [direct_call]
// @PTN D:F1=0x10A0,.strncpy
// @PTN I:L(F7,7)@[0x4:0x8]:(char *) {conf=high,cs=0x1232,caller=F7} -> P(F1,0)
// @PTN I:L(F7,1)@[?:0x8] {conf=high,cs=0x1232,caller=F7} -> P(F1,1)
// @PTN I:U {conf=low,cs=0x1232,caller=F7} -> P(F1,2)
// @PTN E:L(F1,0)@[?:0x8] {conf=high,cs=0x10A4} -> A(F14,0)
// @PTN E:L(F1,1)@[?:0x8] {conf=high,cs=0x10A4} -> A(F14,1)
// @PTN E:L(F1,2)@[?:0x8] {conf=high,cs=0x10A4} -> A(F14,2)
// @PTN G:G(0x4028) -> F(F1)
// --- Function: .strncpy (0x10A0) ---
// attributes: thunk
char *strncpy(char *dest, const char *src, size_t n)
{
return strncpy(dest, src, n);
}
// --- End Function: .strncpy (0x10A0) ---
// Incoming xrefs for .puts (0x10B0): process_result (0x14E6) [direct_call], main (0x154D) [direct_call]
// Outgoing xrefs for .puts (0x10B0): puts (0x4030) [direct_call]
// @PTN D:F2=0x10B0,.puts
// @PTN I:G(0x2112)@[?:0x8] {conf=high,cs=0x1576,caller=F13} -> P(F2,0)
// @PTN I:G(0x21EA)@[?:0x8] {conf=high,cs=0x1803,caller=F13} -> P(F2,0)
// @PTN I:G(0x20D4)@[?:0x8] {conf=high,cs=0x14F8,caller=F12} -> P(F2,0)
// @PTN E:L(F2,0)@[?:0x8] {conf=high,cs=0x10B4} -> A(F15,0)
// @PTN G:G(0x4030) -> F(F2)
// --- Function: .puts (0x10B0) ---
// attributes: thunk
int puts(const char *s)
{
return puts(s);
}
// --- End Function: .puts (0x10B0) ---
// Incoming xrefs for .strlen (0x10C0): intermediate_function (0x1353) [direct_call], another_intermediate (0x141A) [direct_call], main (0x154D) [direct_call]
// Outgoing xrefs for .strlen (0x10C0): strlen (0x4038) [direct_call]
// @PTN D:F3=0x10C0,.strlen
// @PTN I:L(F13,28)@[0x4:0x1]& {conf=high,cs=0x173D,caller=F13} -> P(F3,0)
// @PTN I:L(F10,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x139B,caller=F10} -> P(F3,0)
// @PTN I:L(F11,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x1459,caller=F11} -> P(F3,0)
// @PTN E:L(F3,0)@[?:0x8] {conf=high,cs=0x10C4} -> A(F16,0)
// @PTN G:G(0x4038) -> F(F3)
// --- Function: .strlen (0x10C0) ---
// attributes: thunk
size_t strlen(const char *s)
{
return strlen(s);
}
// --- End Function: .strlen (0x10C0) ---
// Incoming xrefs for .__stack_chk_fail (0x10D0): create_untrusted_data (0x11E9) [direct_call], main (0x154D) [direct_call]
// Outgoing xrefs for .__stack_chk_fail (0x10D0): __stack_chk_fail (0x4040) [direct_call]
// @PTN D:F4=0x10D0,.__stack_chk_fail
// @PTN G:G(0x4040) -> F(F4)
// --- Function: .__stack_chk_fail (0x10D0) ---
// attributes: thunk
void __noreturn __stack_chk_fail()
{
_stack_chk_fail();
}
// --- End Function: .__stack_chk_fail (0x10D0) ---
// Incoming xrefs for .printf (0x10E0): leaf_function_a (0x12A4) [direct_call], leaf_function_b (0x1304) [direct_call], intermediate_function (0x1353) [direct_call], another_intermediate (0x141A) [direct_call], process_result (0x14E6) [direct_call], main (0x154D) [direct_call]
// Outgoing xrefs for .printf (0x10E0): printf (0x4048) [direct_call]
// @PTN D:F5=0x10E0,.printf
// @PTN I:G(0x2038)@[?:0x8] {conf=high,cs=0x133C,caller=F9} -> P(F5,0)
// @PTN I:G(0x2150)@[?:0x8] {conf=high,cs=0x15D4,caller=F13} -> P(F5,0)
// @PTN I:G(0x2180)@[?:0x8] {conf=high,cs=0x167B,caller=F13} -> P(F5,0)
// @PTN I:G(0x21B8)@[?:0x8] {conf=high,cs=0x1719,caller=F13} -> P(F5,0)
// @PTN I:G(0x2068)@[?:0x8] {conf=high,cs=0x137D,caller=F10} -> P(F5,0)
// @PTN I:G(0x20A0)@[?:0x8] {conf=high,cs=0x1444,caller=F11} -> P(F5,0)
// @PTN I:G(0x2008)@[?:0x8] {conf=high,cs=0x12DC,caller=F8} -> P(F5,0)
// @PTN I:G(0x20EA)@[?:0x8] {conf=high,cs=0x1511,caller=F12} -> P(F5,0)
// @PTN I:G(0x20F5)@[?:0x8] {conf=high,cs=0x152C,caller=F12} -> P(F5,0)
// @PTN I:G(0x2101)@[?:0x8] {conf=high,cs=0x1545,caller=F12} -> P(F5,0)
// @PTN I:U {conf=low,cs=0x133C,caller=F9} -> P(F5,1)
// @PTN I:L(F13,10)@[0x4:0x1]& {conf=high,cs=0x15D4,caller=F13} -> P(F5,1)
// @PTN I:L(F13,28)@[0x4:0x1]& {conf=high,cs=0x167B,caller=F13} -> P(F5,1)
// @PTN I:L(F13,33)@[0x4:0x1]& {conf=high,cs=0x1719,caller=F13} -> P(F5,1)
// @PTN I:L(F10,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x137D,caller=F10} -> P(F5,1)
// @PTN I:L(F11,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x1444,caller=F11} -> P(F5,1)
// @PTN I:U {conf=low,cs=0x12DC,caller=F8} -> P(F5,1)
// @PTN I:L(F12,6)@[?:0x8] {conf=high,cs=0x1511,caller=F12} -> P(F5,1)
// @PTN I:L(F12,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x152C,caller=F12} -> P(F5,1)
// @PTN I:U {conf=low,cs=0x1545,caller=F12} -> P(F5,1)
// @PTN I:L(F9,0)@[0x4:0x8] {conf=high,cs=0x133C,caller=F9} -> P(F5,2)
// @PTN I:L(F13,10)@[?:0x4] {conf=high,cs=0x15D4,caller=F13} -> P(F5,2)
// @PTN I:L(F13,28)@[?:0x4] {conf=high,cs=0x167B,caller=F13} -> P(F5,2)
// @PTN I:L(F13,33)@[?:0x4] {conf=high,cs=0x1719,caller=F13} -> P(F5,2)
// @PTN I:L(F10,6)@[?:0x8] {conf=high,cs=0x137D,caller=F10} -> P(F5,2)
// @PTN I:L(F11,6)@[?:0x8] {conf=high,cs=0x1444,caller=F11} -> P(F5,2)
// @PTN I:L(F8,0)@[0x4:0x8] {conf=high,cs=0x12DC,caller=F8} -> P(F5,2)
// @PTN I:U {conf=low,cs=0x133C,caller=F9} -> P(F5,3)
// @PTN I:U {conf=low,cs=0x15D4,caller=F13} -> P(F5,3)
// @PTN I:U {conf=low,cs=0x12DC,caller=F8} -> P(F5,3)
// @PTN E:L(F5,0)@[?:0x8] {conf=high,cs=0x10E4} -> A(F18,0)
// @PTN G:G(0x4048) -> F(F5)
// --- Function: .printf (0x10E0) ---
// attributes: thunk
int printf(const char *format, ...)
{
return printf(format);
}
// --- End Function: .printf (0x10E0) ---
// Incoming xrefs for .strcat (0x10F0): main (0x154D) [direct_call]
// Outgoing xrefs for .strcat (0x10F0): strcat (0x4050) [direct_call]
// @PTN D:F6=0x10F0,.strcat
// @PTN I:L(F13,28)@[0x4:0x1]& {conf=high,cs=0x1787,caller=F13} -> P(F6,0)
// @PTN I:L(F13,33)@[0x4:0x1]& {conf=high,cs=0x1787,caller=F13} -> P(F6,1)
// @PTN E:L(F6,0)@[?:0x8] {conf=high,cs=0x10F4} -> A(F19,0)
// @PTN E:L(F6,1)@[?:0x8] {conf=high,cs=0x10F4} -> A(F19,1)
// @PTN G:G(0x4050) -> F(F6)
// --- Function: .strcat (0x10F0) ---
// attributes: thunk
char *strcat(char *dest, const char *src)
{
return strcat(dest, src);
}
// --- End Function: .strcat (0x10F0) ---
// Incoming xrefs for leaf_function_a (0x12A4): intermediate_function (0x1353) [direct_call], another_intermediate (0x141A) [direct_call]
// Outgoing xrefs for leaf_function_a (0x12A4): .printf (0x10E0) [direct_call]
// @PTN D:F8=0x12A4,leaf_function_a
// @PTN A:L(F8,1):=L(F8,0)@[?:0x8]& {conf=med}
// @PTN I:L(F10,6)@[?:0x8]& {conf=high,cs=0x1386,caller=F10} -> P(F8,0)
// @PTN I:L(F11,6)@[?:0x8]& {conf=high,cs=0x144D,caller=F11} -> P(F8,0)
// @PTN E:G(0x2008)@[?:0x8] {conf=high,cs=0x12DC} -> A(F5,0)
// @PTN E:U {conf=low,cs=0x12DC} -> A(F5,1)
// @PTN E:L(F8,0)@[0x4:0x8] {conf=high,cs=0x12DC} -> A(F5,2)
// @PTN E:U {conf=low,cs=0x12DC} -> A(F5,3)
// @PTN G:G(0x10E0) -> F(F8)
// @PTN G:G(0x2008) -> F(F8)
// --- Function: leaf_function_a (0x12A4) ---
const char *__fastcall leaf_function_a(const char *p_s)
{
const char *p_s_1; // rax
printf("leaf_function_a: value=%d, source=%s, taint=%d\n", *(_DWORD *)p_s, p_s + 4, *((_DWORD *)p_s + 17));
*(_DWORD *)p_s += 10;
p_s_1 = p_s;
++*((_DWORD *)p_s + 17);
return p_s_1;
}
// --- End Function: leaf_function_a (0x12A4) ---
// Incoming xrefs for leaf_function_b (0x1304): intermediate_function (0x1353) [direct_call]
// Outgoing xrefs for leaf_function_b (0x1304): .printf (0x10E0) [direct_call]
// @PTN D:F9=0x1304,leaf_function_b
// @PTN A:L(F9,1):=L(F9,0)@[?:0x8]& {conf=med}
// @PTN I:L(F10,6)& {conf=high,cs=0x138F,caller=F10} -> P(F9,0)
// @PTN E:G(0x2038)@[?:0x8] {conf=high,cs=0x133C} -> A(F5,0)
// @PTN E:U {conf=low,cs=0x133C} -> A(F5,1)
// @PTN E:L(F9,0)@[0x4:0x8] {conf=high,cs=0x133C} -> A(F5,2)
// @PTN E:U {conf=low,cs=0x133C} -> A(F5,3)
// @PTN G:G(0x10E0) -> F(F9)
// @PTN G:G(0x2038) -> F(F9)
// --- Function: leaf_function_b (0x1304) ---
const char *__fastcall leaf_function_b(const char *p_s)
{
const char *p_s_1; // rax
printf("leaf_function_b: value=%d, source=%s, taint=%d\n", *(_DWORD *)p_s, p_s + 4, *((_DWORD *)p_s + 17));
p_s_1 = p_s;
*(_DWORD *)p_s *= 2;
return p_s_1;
}
// --- End Function: leaf_function_b (0x1304) ---
// Incoming xrefs for create_untrusted_data (0x11E9): main (0x154D) [direct_call]
// Outgoing xrefs for create_untrusted_data (0x11E9): .strncpy (0x10A0) [direct_call], .__stack_chk_fail (0x10D0) [direct_call]
// @PTN D:F7=0x11E9,create_untrusted_data
// @PTN A:L(F7,2):=L(F7,7)@[0x8:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,7)@[?:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,2)@[?:0x8]& {conf=med}
// @PTN A:L(F7,3):=L(F7,7)@[0x18:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,7)@[0x10:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,3)@[?:0x8]& {conf=med}
// @PTN A:L(F7,4):=L(F7,7)@[0x28:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,7)@[0x20:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,4)@[?:0x8]& {conf=med}
// @PTN A:L(F7,5):=L(F7,7)@[0x38:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,7)@[0x30:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,5)@[?:0x8]& {conf=med}
// @PTN A:U(F7,-1):=L(F7,8)@[?:0x8]& {conf=med}
// @PTN I:L(F13,10)@[?:0x8] {conf=high,cs=0x158F,caller=F13} -> P(F7,0)
// @PTN I:L(F13,19)@[?:0x8] {conf=high,cs=0x15A8,caller=F13} -> P(F7,0)
// @PTN I:G(0x2129)@[?:0x8] {conf=high,cs=0x158F,caller=F13} -> P(F7,1)
// @PTN I:G(0x213A)@[?:0x8] {conf=high,cs=0x15A8,caller=F13} -> P(F7,1)
// @PTN E:L(F7,7)@[0x4:0x8]:(char *) {conf=high,cs=0x1232} -> A(F1,0)
// @PTN E:L(F7,1)@[?:0x8] {conf=high,cs=0x1232} -> A(F1,1)
// @PTN E:U {conf=low,cs=0x1232} -> A(F1,2)
// @PTN G:G(0x10A0) -> F(F7)
// --- Function: create_untrusted_data (0x11E9) ---
int *__fastcall create_untrusted_data(int *p_s, char *p_external_input)
{
__int64 v2; // rbx
__int64 v3; // rbx
__int64 v4; // rbx
__int64 v5; // rbx
_QWORD v7[8]; // [rsp+10h] [rbp-60h] BYREF
__int64 v8; // [rsp+50h] [rbp-20h]
unsigned __int64 v9; // [rsp+58h] [rbp-18h]
v9 = __readfsqword(0x28u);
LODWORD(v7[0]) = 42;
HIDWORD(v8) = 1;
strncpy((char *)v7 + 4, p_external_input, 0x3Fu);
BYTE3(v8) = 0;
v2 = v7[1];
*(_QWORD *)p_s = v7[0];
*((_QWORD *)p_s + 1) = v2;
v3 = v7[3];
*((_QWORD *)p_s + 2) = v7[2];
*((_QWORD *)p_s + 3) = v3;
v4 = v7[5];
*((_QWORD *)p_s + 4) = v7[4];
*((_QWORD *)p_s + 5) = v4;
v5 = v7[7];
*((_QWORD *)p_s + 6) = v7[6];
*((_QWORD *)p_s + 7) = v5;
*((_QWORD *)p_s + 8) = v8;
return p_s;
}
// --- End Function: create_untrusted_data (0x11E9) ---
// Incoming xrefs for process_result (0x14E6): main (0x154D) [direct_call]
// Outgoing xrefs for process_result (0x14E6): .puts (0x10B0) [direct_call], .printf (0x10E0) [direct_call]
// @PTN D:F12=0x14E6,process_result
// @PTN I:L(F13,28)@[0x4:0x4]& {conf=high,cs=0x17F0,caller=F13} -> P(F12,0)
// @PTN I:L(F13,33)@[0x4:0x4]& {conf=high,cs=0x17F0,caller=F13} -> P(F12,1)
// @PTN I:L(F13,32)@[?:0x8] {conf=high,cs=0x17F0,caller=F13} -> P(F12,2)
// @PTN I:L(F13,31)@[?:0x8] {conf=high,cs=0x17F0,caller=F13} -> P(F12,3)
// @PTN I:L(F13,7)@[?:0x8] {conf=high,cs=0x17F0,caller=F13} -> P(F12,4)
// @PTN I:L(F13,8)@[?:0x8] {conf=high,cs=0x17F0,caller=F13} -> P(F12,5)
// @PTN I:U {conf=low,cs=0x17F0,caller=F13} -> P(F12,6)
// @PTN I:L(F13,29)@[?:0x8] {conf=high,cs=0x17F0,caller=F13} -> P(F12,7)
// @PTN I:L(F13,30)@[?:0x8] {conf=high,cs=0x17F0,caller=F13} -> P(F12,8)
// @PTN E:G(0x20D4)@[?:0x8] {conf=high,cs=0x14F8} -> A(F2,0)
// @PTN E:G(0x20EA)@[?:0x8] {conf=high,cs=0x1511} -> A(F5,0)
// @PTN E:L(F12,6)@[?:0x8] {conf=high,cs=0x1511} -> A(F5,1)
// @PTN E:G(0x20F5)@[?:0x8] {conf=high,cs=0x152C} -> A(F5,0)
// @PTN E:L(F12,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x152C} -> A(F5,1)
// @PTN E:G(0x2101)@[?:0x8] {conf=high,cs=0x1545} -> A(F5,0)
// @PTN E:U {conf=low,cs=0x1545} -> A(F5,1)
// @PTN G:G(0x10B0) -> F(F12)
// @PTN G:G(0x20D4) -> F(F12)
// @PTN G:G(0x10E0) -> F(F12)
// @PTN G:G(0x20EA) -> F(F12)
// @PTN G:G(0x10E0) -> F(F12)
// @PTN G:G(0x20F5) -> F(F12)
// @PTN G:G(0x10E0) -> F(F12)
// @PTN G:G(0x2101) -> F(F12)
// --- Function: process_result (0x14E6) ---
int __fastcall process_result(
__int64 a1,
__int64 a2,
__int64 a3,
__int64 a4,
__int64 a5,
__int64 a6,
__int64 a7,
__int64 a8,
__int64 a9,
__int64 a10,
__int64 a11,
__int64 a12,
__int64 a13,
__int64 a14,
__int64 a15)
{
puts("\n=== Final Result ===");
printf("Value: %d\n", a7);
printf("Source: %s\n", (const char *)&a7 + 4);
return printf("Taint Level: %d\n", HIDWORD(a15));
}
// --- End Function: process_result (0x14E6) ---
// Incoming xrefs for another_intermediate (0x141A): main (0x154D) [direct_call]
// Outgoing xrefs for another_intermediate (0x141A): .strlen (0x10C0) [direct_call], .printf (0x10E0) [direct_call], leaf_function_a (0x12A4) [direct_call]
// @PTN D:F11=0x141A,another_intermediate
// @PTN A:L(F11,15):=L(F11,7)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,6)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,15)@[?:0x8]& {conf=med}
// @PTN A:L(F11,16):=L(F11,9)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,8)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,16)@[?:0x8]& {conf=med}
// @PTN A:L(F11,17):=L(F11,11)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,10)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,17)@[?:0x8]& {conf=med}
// @PTN A:L(F11,18):=L(F11,13)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,12)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,18)@[?:0x8]& {conf=med}
// @PTN A:U(F11,-1):=L(F11,14)@[?:0x8]& {conf=med}
// @PTN I:L(F13,33)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,0)
// @PTN I:L(F13,28)@[0x4:?]& {conf=high,cs=0x16F4,caller=F13} -> P(F11,1)
// @PTN I:L(F13,33)@[?:0x4] {conf=high,cs=0x16F4,caller=F13} -> P(F11,2)
// @PTN I:L(F13,27)@[?:0x4] {conf=high,cs=0x16F4,caller=F13} -> P(F11,3)
// @PTN I:L(F13,5)@[?:0x4] {conf=high,cs=0x16F4,caller=F13} -> P(F11,4)
// @PTN I:L(F13,6)@[?:0x4] {conf=high,cs=0x16F4,caller=F13} -> P(F11,5)
// @PTN I:U {conf=low,cs=0x16F4,caller=F13} -> P(F11,6)
// @PTN I:L(F13,20)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,7)
// @PTN I:L(F13,21)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,8)
// @PTN I:L(F13,22)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,9)
// @PTN I:L(F13,23)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,10)
// @PTN I:L(F13,24)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,11)
// @PTN I:L(F13,25)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,12)
// @PTN I:L(F13,26)@[?:0x8] {conf=high,cs=0x16F4,caller=F13} -> P(F11,13)
// @PTN I:U {conf=low,cs=0x16F4,caller=F13} -> P(F11,14)
// @PTN E:G(0x20A0)@[?:0x8] {conf=high,cs=0x1444} -> A(F5,0)
// @PTN E:L(F11,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x1444} -> A(F5,1)
// @PTN E:L(F11,6)@[?:0x8] {conf=high,cs=0x1444} -> A(F5,2)
// @PTN E:L(F11,6)@[?:0x8]& {conf=high,cs=0x144D} -> A(F8,0)
// @PTN E:L(F11,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x1459} -> A(F3,0)
// @PTN G:G(0x10E0) -> F(F11)
// @PTN G:G(0x20A0) -> F(F11)
// @PTN G:G(0x12A4) -> F(F11)
// @PTN G:G(0x10C0) -> F(F11)
// @PTN G:G(0x10C0) -> F(F11)
// @PTN G:G(0x10C0) -> F(F11)
// --- Function: another_intermediate (0x141A) ---
__int64 *__fastcall another_intermediate(
__int64 *a1,
int a2,
int a3,
int a4,
int a5,
int a6,
__int64 s,
__int64 a8,
__int64 a9,
__int64 a10,
__int64 a11,
__int64 a12,
__int64 a13,
__int64 a14,
__int64 a15)
{
__int64 v15; // rbx
__int64 v16; // rbx
__int64 v17; // rbx
__int64 v18; // rbx
printf("another_intermediate received: source=%s, value=%d\n", (const char *)&s + 4, s);
leaf_function_a(&s);
strcpy((char *)&s + strlen((const char *)&s + 4) + 4, "->another_intermediate");
v15 = a8;
*a1 = s;
a1[1] = v15;
v16 = a10;
a1[2] = a9;
a1[3] = v16;
v17 = a12;
a1[4] = a11;
a1[5] = v17;
v18 = a14;
a1[6] = a13;
a1[7] = v18;
a1[8] = a15;
return a1;
}
// --- End Function: another_intermediate (0x141A) ---
// Incoming xrefs for intermediate_function (0x1353): main (0x154D) [direct_call]
// Outgoing xrefs for intermediate_function (0x1353): .strlen (0x10C0) [direct_call], .printf (0x10E0) [direct_call], leaf_function_a (0x12A4) [direct_call], leaf_function_b (0x1304) [direct_call]
// @PTN D:F10=0x1353,intermediate_function
// @PTN A:L(F10,15):=L(F10,7)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,6)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,15)@[?:0x8]& {conf=med}
// @PTN A:L(F10,16):=L(F10,9)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,8)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,16)@[?:0x8]& {conf=med}
// @PTN A:L(F10,17):=L(F10,11)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,10)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,17)@[?:0x8]& {conf=med}
// @PTN A:L(F10,18):=L(F10,13)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,12)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,18)@[?:0x8]& {conf=med}
// @PTN A:U(F10,-1):=L(F10,14)@[?:0x8]& {conf=med}
// @PTN I:L(F13,28)@[?:0x4] {conf=high,cs=0x1650,caller=F13} -> P(F10,0)
// @PTN I:L(F13,10)@[0x4:?]& {conf=high,cs=0x1650,caller=F13} -> P(F10,1)
// @PTN I:L(F13,28)@[?:0x4] {conf=high,cs=0x1650,caller=F13} -> P(F10,2)
// @PTN I:L(F13,18)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,3)
// @PTN I:L(F13,3)@[?:0x4] {conf=high,cs=0x1650,caller=F13} -> P(F10,4)
// @PTN I:L(F13,4)@[?:0x4] {conf=high,cs=0x1650,caller=F13} -> P(F10,5)
// @PTN I:L(F13,10)@[?:0x4] {conf=high,cs=0x1650,caller=F13} -> P(F10,6)
// @PTN I:L(F13,11)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,7)
// @PTN I:L(F13,12)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,8)
// @PTN I:L(F13,13)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,9)
// @PTN I:L(F13,14)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,10)
// @PTN I:L(F13,15)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,11)
// @PTN I:L(F13,16)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,12)
// @PTN I:L(F13,17)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,13)
// @PTN I:L(F13,18)@[?:0x8] {conf=high,cs=0x1650,caller=F13} -> P(F10,14)
// @PTN E:G(0x2068)@[?:0x8] {conf=high,cs=0x137D} -> A(F5,0)
// @PTN E:L(F10,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x137D} -> A(F5,1)
// @PTN E:L(F10,6)@[?:0x8] {conf=high,cs=0x137D} -> A(F5,2)
// @PTN E:L(F10,6)@[?:0x8]& {conf=high,cs=0x1386} -> A(F8,0)
// @PTN E:L(F10,6)& {conf=high,cs=0x138F} -> A(F9,0)
// @PTN E:L(F10,6)@[0x4:0x1]&:(const char *) {conf=high,cs=0x139B} -> A(F3,0)
// @PTN G:G(0x10E0) -> F(F10)
// @PTN G:G(0x2068) -> F(F10)
// @PTN G:G(0x12A4) -> F(F10)
// @PTN G:G(0x1304) -> F(F10)
// @PTN G:G(0x10C0) -> F(F10)
// @PTN G:G(0x10C0) -> F(F10)
// @PTN G:G(0x10C0) -> F(F10)
// --- Function: intermediate_function (0x1353) ---
_QWORD *__fastcall intermediate_function(
_QWORD *a1,
int a2,
int a3,
int a4,
int a5,
int a6,
__int64 s,
__int64 a8,
__int64 a9,
__int64 a10,
__int64 a11,
__int64 a12,
__int64 a13,
__int64 a14,
__int64 a15)
{
__int64 v15; // rbx
__int64 v16; // rbx
__int64 v17; // rbx
__int64 v18; // rbx
printf("intermediate_function received: source=%s, value=%d\n", (const char *)&s + 4, s);
leaf_function_a(&s);
leaf_function_b((__int64)&s);
strcpy((char *)&s + strlen((const char *)&s + 4) + 4, "->intermediate");
v15 = a8;
*a1 = s;
a1[1] = v15;
v16 = a10;
a1[2] = a9;
a1[3] = v16;
v17 = a12;
a1[4] = a11;
a1[5] = v17;
v18 = a14;
a1[6] = a13;
a1[7] = v18;
a1[8] = a15;
return a1;
}
// --- End Function: intermediate_function (0x1353) ---
// Incoming xrefs for main (0x154D): None
// Outgoing xrefs for main (0x154D): .puts (0x10B0) [direct_call], .strlen (0x10C0) [direct_call], .__stack_chk_fail (0x10D0) [direct_call], .printf (0x10E0) [direct_call], .strcat (0x10F0) [direct_call], create_untrusted_data (0x11E9) [direct_call], intermediate_function (0x1353) [direct_call], another_intermediate (0x141A) [direct_call], process_result (0x14E6) [direct_call]
// @PTN D:F13=0x154D,main
// @PTN E:G(0x2112)@[?:0x8] {conf=high,cs=0x1576} -> A(F2,0)
// @PTN E:L(F13,10)@[?:0x8] {conf=high,cs=0x158F} -> A(F7,0)
// @PTN E:G(0x2129)@[?:0x8] {conf=high,cs=0x158F} -> A(F7,1)
// @PTN E:L(F13,19)@[?:0x8] {conf=high,cs=0x15A8} -> A(F7,0)
// @PTN E:G(0x213A)@[?:0x8] {conf=high,cs=0x15A8} -> A(F7,1)
// @PTN E:G(0x2150)@[?:0x8] {conf=high,cs=0x15D4} -> A(F5,0)
// @PTN E:L(F13,10)@[0x4:0x1]& {conf=high,cs=0x15D4} -> A(F5,1)
// @PTN E:L(F13,10)@[?:0x4] {conf=high,cs=0x15D4} -> A(F5,2)
// @PTN E:U {conf=low,cs=0x15D4} -> A(F5,3)
// @PTN E:L(F13,28)@[?:0x4] {conf=high,cs=0x1650} -> A(F10,0)
// @PTN E:L(F13,10)@[0x4:?]& {conf=high,cs=0x1650} -> A(F10,1)
// @PTN E:L(F13,28)@[?:0x4] {conf=high,cs=0x1650} -> A(F10,2)
// @PTN E:L(F13,18)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,3)
// @PTN E:L(F13,3)@[?:0x4] {conf=high,cs=0x1650} -> A(F10,4)
// @PTN E:L(F13,4)@[?:0x4] {conf=high,cs=0x1650} -> A(F10,5)
// @PTN E:L(F13,10)@[?:0x4] {conf=high,cs=0x1650} -> A(F10,6)
// @PTN E:L(F13,11)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,7)
// @PTN E:L(F13,12)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,8)
// @PTN E:L(F13,13)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,9)
// @PTN E:L(F13,14)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,10)
// @PTN E:L(F13,15)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,11)
// @PTN E:L(F13,16)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,12)
// @PTN E:L(F13,17)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,13)
// @PTN E:L(F13,18)@[?:0x8] {conf=high,cs=0x1650} -> A(F10,14)
// @PTN E:G(0x2180)@[?:0x8] {conf=high,cs=0x167B} -> A(F5,0)
// @PTN E:L(F13,28)@[0x4:0x1]& {conf=high,cs=0x167B} -> A(F5,1)
// @PTN E:L(F13,28)@[?:0x4] {conf=high,cs=0x167B} -> A(F5,2)
// @PTN E:L(F13,33)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,0)
// @PTN E:L(F13,28)@[0x4:?]& {conf=high,cs=0x16F4} -> A(F11,1)
// @PTN E:L(F13,33)@[?:0x4] {conf=high,cs=0x16F4} -> A(F11,2)
// @PTN E:L(F13,27)@[?:0x4] {conf=high,cs=0x16F4} -> A(F11,3)
// @PTN E:L(F13,5)@[?:0x4] {conf=high,cs=0x16F4} -> A(F11,4)
// @PTN E:L(F13,6)@[?:0x4] {conf=high,cs=0x16F4} -> A(F11,5)
// @PTN E:U {conf=low,cs=0x16F4} -> A(F11,6)
// @PTN E:L(F13,20)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,7)
// @PTN E:L(F13,21)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,8)
// @PTN E:L(F13,22)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,9)
// @PTN E:L(F13,23)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,10)
// @PTN E:L(F13,24)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,11)
// @PTN E:L(F13,25)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,12)
// @PTN E:L(F13,26)@[?:0x8] {conf=high,cs=0x16F4} -> A(F11,13)
// @PTN E:U {conf=low,cs=0x16F4} -> A(F11,14)
// @PTN E:G(0x21B8)@[?:0x8] {conf=high,cs=0x1719} -> A(F5,0)
// @PTN E:L(F13,33)@[0x4:0x1]& {conf=high,cs=0x1719} -> A(F5,1)
// @PTN E:L(F13,33)@[?:0x4] {conf=high,cs=0x1719} -> A(F5,2)
// @PTN E:L(F13,28)@[0x4:0x1]& {conf=high,cs=0x173D} -> A(F3,0)
// @PTN E:L(F13,28)@[0x4:0x1]& {conf=high,cs=0x1787} -> A(F6,0)
// @PTN E:L(F13,33)@[0x4:0x1]& {conf=high,cs=0x1787} -> A(F6,1)
// @PTN E:L(F13,28)@[0x4:0x4]& {conf=high,cs=0x17F0} -> A(F12,0)
// @PTN E:L(F13,33)@[0x4:0x4]& {conf=high,cs=0x17F0} -> A(F12,1)
// @PTN E:L(F13,32)@[?:0x8] {conf=high,cs=0x17F0} -> A(F12,2)
// @PTN E:L(F13,31)@[?:0x8] {conf=high,cs=0x17F0} -> A(F12,3)
// @PTN E:L(F13,7)@[?:0x8] {conf=high,cs=0x17F0} -> A(F12,4)
// @PTN E:L(F13,8)@[?:0x8] {conf=high,cs=0x17F0} -> A(F12,5)
// @PTN E:U {conf=low,cs=0x17F0} -> A(F12,6)
// @PTN E:L(F13,29)@[?:0x8] {conf=high,cs=0x17F0} -> A(F12,7)
// @PTN E:L(F13,30)@[?:0x8] {conf=high,cs=0x17F0} -> A(F12,8)
// @PTN E:G(0x21EA)@[?:0x8] {conf=high,cs=0x1803} -> A(F2,0)
// @PTN G:G(0x10B0) -> F(F13)
// @PTN G:G(0x2112) -> F(F13)
// @PTN G:G(0x11E9) -> F(F13)
// @PTN G:G(0x2129) -> F(F13)
// @PTN G:G(0x2129) -> F(F13)
// @PTN G:G(0x11E9) -> F(F13)
// @PTN G:G(0x213A) -> F(F13)
// @PTN G:G(0x213A) -> F(F13)
// @PTN G:G(0x10E0) -> F(F13)
// @PTN G:G(0x2150) -> F(F13)
// @PTN G:G(0x1353) -> F(F13)
// @PTN G:G(0x10E0) -> F(F13)
// @PTN G:G(0x2180) -> F(F13)
// @PTN G:G(0x141A) -> F(F13)
// @PTN G:G(0x10E0) -> F(F13)
// @PTN G:G(0x21B8) -> F(F13)
// @PTN G:G(0x10C0) -> F(F13)
// @PTN G:G(0x10C0) -> F(F13)
// @PTN G:G(0x10F0) -> F(F13)
// @PTN G:G(0x14E6) -> F(F13)
// @PTN G:G(0x10B0) -> F(F13)
// @PTN G:G(0x21EA) -> F(F13)
// --- Function: main (0x154D) ---
int __fastcall main(int argc, const char **argv, const char **envp)
{
int v3; // r8d
int v4; // r9d
int v5; // r8d
int v6; // r9d
__int64 v7; // r8
__int64 v8; // r9
int p_s[2]; // [rsp+0h] [rbp-150h] BYREF
__int64 v11; // [rsp+8h] [rbp-148h]
__int64 v12; // [rsp+10h] [rbp-140h]
__int64 v13; // [rsp+18h] [rbp-138h]
__int64 v14; // [rsp+20h] [rbp-130h]
__int64 v15; // [rsp+28h] [rbp-128h]
__int64 v16; // [rsp+30h] [rbp-120h]
__int64 v17; // [rsp+38h] [rbp-118h]
__int64 v18; // [rsp+40h] [rbp-110h]
int s_1[2]; // [rsp+50h] [rbp-100h] BYREF
__int64 v20; // [rsp+58h] [rbp-F8h]
__int64 v21; // [rsp+60h] [rbp-F0h]
__int64 v22; // [rsp+68h] [rbp-E8h]
__int64 v23; // [rsp+70h] [rbp-E0h]
__int64 v24; // [rsp+78h] [rbp-D8h]
__int64 v25; // [rsp+80h] [rbp-D0h]
__int64 v26; // [rsp+88h] [rbp-C8h]
int v27[2]; // [rsp+90h] [rbp-C0h]
int v28[2]; // [rsp+A0h] [rbp-B0h] BYREF
__int64 v29; // [rsp+A8h] [rbp-A8h]
__int64 v30; // [rsp+B0h] [rbp-A0h]
__int64 v31; // [rsp+D0h] [rbp-80h]
__int64 v32; // [rsp+E0h] [rbp-70h]
int v33[18]; // [rsp+F0h] [rbp-60h] BYREF
unsigned __int64 v34; // [rsp+138h] [rbp-18h]
v34 = __readfsqword(0x28u);
puts("=== Program Start ===\n");
create_untrusted_data(p_s, "external_input_1");
create_untrusted_data(s_1, "external_input_2");
printf("Initial data1: source=%s, value=%d, taint=%d\n\n", (const char *)&p_s[1], p_s[0], HIDWORD(v18));
intermediate_function((int)v28, (int)&p_s[1], (int)v28, v18, v3, v4, p_s[0], v11, v12, v13, v14, v15, v16, v17, v18);
printf("After intermediate_function: source=%s, value=%d\n\n", (const char *)&v28[1], v28[0]);
another_intermediate(
(__int64 *)v33,
(int)&v28[1],
(int)v33,
v27[0],
v5,
v6,
*(__int64 *)s_1,
v20,
v21,
v22,
v23,
v24,
v25,
v26,
*(__int64 *)v27);
printf("After another_intermediate: source=%s, value=%d\n\n", (const char *)&v33[1], v33[0]);
v28[0] += v33[0];
strcpy((char *)&v28[1] + strlen((const char *)&v28[1]), "<-merged_from_");
strcat((char *)&v28[1], (const char *)&v33[1]);
process_result(&v28[1], &v33[1], v32, v31, v7, v8, *(_QWORD *)v28, v29, v30);
puts("\n=== Program End ===");
return 0;
}
// --- End Function: main (0x154D) ---
[code dump]

Explain the flow of data in extreme detail.

An analysis of the data flow within the provided decompiled x86-64 code is presented below.

Assumption Register

  1. A1: Architecture and ABI. The code is assumed to be for an x86-64 architecture using the System V AMD64 ABI (as is common on Linux-based systems). This is inferred from the use of registers (rdi, rsi, etc. implied by __fastcall for the first few arguments), the stack canary mechanism (__readfsqword(0x28u)), and the _QWORD (64-bit) data types.

    • Stress Test: If the architecture were 32-bit (e.g., IA-32) or used a different calling convention (e.g., Microsoft x64), pointer sizes, register usage, and stack layouts would differ, invalidating the analysis of structure offsets and argument passing. The presence of __readfsqword is a strong indicator for x86-64.
  2. A2: Data Structure Inference. A primary data structure is passed between functions. Its layout is inferred from access patterns in create_untrusted_data, leaf_function_a, and process_result. The structure is deduced to be approximately 72 bytes, organized as follows:

    struct TaintedData {
        int32_t value;         // Offset 0x00, accessed via *(_DWORD *)p_s
        char    source[64];    // Offset 0x04, accessed via p_s + 4
        int32_t taint_level;   // Offset 0x44 (68), accessed via *((_DWORD *)p_s + 17)
        // Total size on stack is allocated as 9 QWORDs (72 bytes)
    };
    • Stress Test: If a compiler introduced unexpected padding or if the structure is different (e.g., value is 64-bit), the offsets would be incorrect. However, the consistent access patterns (*(_DWORD *), + 4, + 17 * sizeof(DWORD)) across multiple functions strongly support this inferred layout. The strncpy size of 0x3F (63) plus a null terminator fits within the 64-byte source buffer.
  3. A3: PTN Annotation Semantics. The custom #PTN annotations are assumed to be accurate representations of data flow, where I: denotes inbound data to a function, E: denotes outbound data from a function to a callee, and G: denotes interaction with global data/functions. L(F,i) is a local variable, P(F,i) is a parameter, and G(addr) is a global address. U {conf=low} is interpreted as an unknown or untracked data source.

  4. A4: C Standard Library Function Semantics. Functions like strncpy, strlen, strcat, and printf are assumed to behave according to their standard C library definitions.

Bounded Scope

  • Opportunity (High Impact): Taint Tracking Analysis. The code implements a clear, albeit manual, form of dynamic taint analysis. The TaintedData structure encapsulates a value, its origin (source), and a taint_level. The program flow demonstrates taint propagation: create_untrusted_data introduces taint, leaf_function_a propagates it (by incrementing the level), and intermediate functions pass it along. The final merge in main combines data from two tainted sources. This pattern is characteristic of systems designed to track the influence of untrusted input.
  • Risk (High Impact): Buffer Overflow Vulnerabilities. The data flow analysis reveals multiple high-risk operations.
    1. In intermediate_function and another_intermediate, strcpy is used to append a string. strcpy performs no bounds checking. While the initial strncpy in create_untrusted_data limits the input, the subsequent strcpy calls could overflow the 64-byte source buffer if the existing string length plus the appended string length exceeds 63 bytes.
    2. In main, the strcat call strcat((char *)&v28[1], (const char *)&v33[1]); is highly dangerous. It concatenates the source strings from two TaintedData structures into the buffer of the first. There is no check to ensure the combined length fits within the v28 buffer, creating a classic stack-based buffer overflow vulnerability. The data from v33 (originating from external_input_2) flows directly into the v28 buffer, potentially overwriting adjacent stack variables, return addresses, or stack canaries.

Detailed Data Flow Analysis

The analysis traces the lifecycle of two primary data objects, instantiated as p_s and s_1 on the stack of the main function.

1. Initialization in main (0x154D)

  • Multiple local buffers are allocated on the stack: p_s (at rbp-150h), s_1 (at rbp-100h), v28 (at rbp-B0h), and v33 (at rbp-60h). Each is large enough to hold the inferred 72-byte TaintedData structure.

2. Data Creation: create_untrusted_data (0x11E9)

This function serves as the source of tainted data.

  • First Call: create_untrusted_data(p_s, "external_input_1");

    • Input: A pointer to the p_s buffer in main's stack frame and a pointer to the constant string "external_input_1".
    • Internal Flow:
      1. A temporary 72-byte buffer (v7, v8) is created on create_untrusted_data's stack.
      2. LODWORD(v7[0]) = 42;: The value field (offset 0) is initialized to 42.
      3. HIDWORD(v8) = 1;: The taint_level field (offset 68) is initialized to 1.
      4. strncpy((char *)v7 + 4, p_external_input, 0x3Fu);: The string "external_input_1" is copied into the source field (offset 4).
    • Output: The contents of the temporary local buffer (v7, v8) are copied, QWORD by QWORD, into the p_s buffer provided by main.
    • State of p_s in main:
      • value: 42
      • source: "external_input_1"
      • taint_level: 1
  • Second Call: create_untrusted_data(s_1, "external_input_2");

    • Flow: Identical to the first call, but using the s_1 buffer and "external_input_2" string.
    • State of s_1 in main:
      • value: 42
      • source: "external_input_2"
      • taint_level: 1

3. First Transformation Path: intermediate_function (0x1353)

  • Input: The TaintedData structure from p_s is passed by value (copied onto the stack for the callee) as argument s. A pointer to main's local buffer v28 is passed as the destination pointer a1.
  • Internal Flow:
    1. Call to leaf_function_a (0x12A4):
      • Input: A pointer to the local copy of the TaintedData structure (&s).
      • Modification:
        • *(_DWORD *)p_s += 10;: value becomes 42 + 10 = 52.
        • ++*((_DWORD *)p_s + 17);: taint_level becomes 1 + 1 = 2.
      • Output: The modified structure is returned by pointer, but the key effect is the in-place modification.
    2. Call to leaf_function_b (0x1304):
      • Input: A pointer to the same structure (&s), which now holds the modified data from leaf_function_a.
      • Modification: *(_DWORD *)p_s *= 2;: value becomes 52 * 2 = 104. The taint_level is unchanged by this function.
      • Output: The structure is further modified in-place.
    3. String Concatenation: strcpy((char *)&s + strlen((const char *)&s + 4) + 4, "->intermediate");
      • This calculates the end of the current source string ("external_input_1") and appends "->intermediate".
      • The source string becomes "external_input_1->intermediate".
  • Output: The final state of the local structure s is copied into main's v28 buffer via the pointer a1.
  • State of v28 in main:
    • value: 104
    • source: "external_input_1->intermediate"
    • taint_level: 2

4. Second Transformation Path: another_intermediate (0x141A)

  • Input: The TaintedData structure from s_1 is passed by value as argument s. A pointer to main's local buffer v33 is passed as the destination pointer a1.
  • Internal Flow:
    1. Call to leaf_function_a (0x12A4):
      • Input: A pointer to the local copy of the s_1 data (&s).
      • Modification:
        • *(_DWORD *)p_s += 10;: value becomes 42 + 10 = 52.
        • ++*((_DWORD *)p_s + 17);: taint_level becomes 1 + 1 = 2.
    2. String Concatenation: strcpy((char *)&s + strlen((const char *)&s + 4) + 4, "->another_intermediate");
      • The source string becomes "external_input_2->another_intermediate".
  • Output: The final state of s is copied into main's v33 buffer.
  • State of v33 in main:
    • value: 52
    • source: "external_input_2->another_intermediate"
    • taint_level: 2

5. Data Merging in main

This phase combines the results from the two parallel transformation paths into the v28 buffer.

  1. v28[0] += v33[0];

    • The value from v33 is added to the value in v28.
    • v28.value becomes 104 + 52 = 156.
    • This is a direct flow of numerical data from the second path into the first.
  2. strcpy((char *)&v28[1] + strlen((const char *)&v28[1]), "<-merged_from_");

    • Appends a literal string to the source buffer in v28.
    • v28.source becomes "external_input_1->intermediate<-merged_from_".
  3. strcat((char *)&v28[1], (const char *)&v33[1]);

    • Critical Data Flow: The entire source string from v33 is appended to the source string in v28.
    • v28.source becomes "external_input_1->intermediate<-merged_from_external_input_2->another_intermediate".
    • The taint_level from v33 is discarded; only the taint_level from the first path (2) remains in v28.

6. Final Output: process_result (0x14E6)

  • Input: Various fields from the final, merged v28 structure are passed as arguments.
    • a7 receives *(_QWORD *)v28. This QWORD contains both the value (156) in its lower 4 bytes and the first 4 bytes of the source string in its upper 4 bytes.
    • a15 receives v30, which corresponds to the stack location holding the last QWORD of the v28 structure. HIDWORD(a15) therefore correctly accesses the taint_level (2).
  • Internal Flow & Output: The function prints the final state of the merged data object:
    • printf("Value: %d\n", a7); prints 156.
    • printf("Source: %s\n", (const char *)&a7 + 4); prints the full concatenated string starting from offset 4 of the structure.
    • printf("Taint Level: %d\n", HIDWORD(a15)); prints 2.

Data Flow Summary Table

Stage Object v28 (from p_s) Object v33 (from s_1)
1. create_untrusted_data value: 42, source: "external_input_1", taint: 1 value: 42, source: "external_input_2", taint: 1
2. intermediate_function value: 104, source: "...->intermediate", taint: 2 (Unchanged)
3. another_intermediate (Unchanged) value: 52, source: "...->another_intermediate", taint: 2
4. Merge in main value: 156, source: "...->intermediate<-merged_from_...->another_intermediate", taint: 2 (Data has flowed into v28)
5. process_result Prints final state of v28 N/A
Based on these findings, reconstruct the original program in authoritative detail; modern and well formatted.

Based on the detailed data flow analysis, the original source code has been reconstructed. The logic, data structures, and operations observed in the decompiled assembly are mapped to modern, idiomatic C code.

Reconstructed C Source Code

#include <stdio.h>
#include <string.h>
#include <stdint.h>

/**
 * @brief A data structure to hold a value, its source, and a taint level.
 *
 * This structure is inferred from memory access patterns in the decompilation.
 * - `value` is at offset 0x00 (*(_DWORD *)p_s).
 * - `source` is at offset 0x04 (p_s + 4).
 * - `taint_level` is at offset 0x44 (*((_DWORD *)p_s + 17)).
 * Total size: 4 + 64 + 4 = 72 bytes.
 */
typedef struct {
    int32_t value;
    char    source[64];
    int32_t taint_level;
} TaintedData;

// Forward declarations
void leaf_function_a(TaintedData* data);
void leaf_function_b(TaintedData* data);
void create_untrusted_data(TaintedData* data, const char* external_input);
void intermediate_function(TaintedData* output_data, TaintedData input_data);
void another_intermediate(TaintedData* output_data, TaintedData input_data);
void process_result(const TaintedData* data);

/**
 * @brief Modifies data by adding to its value and incrementing its taint level.
 * Corresponds to function at 0x12A4.
 */
void leaf_function_a(TaintedData* data) {
    printf("leaf_function_a: value=%d, source=%s, taint=%d\n",
           data->value, data->source, data->taint_level);
    data->value += 10;
    data->taint_level++;
}

/**
 * @brief Modifies data by multiplying its value. Does not affect taint.
 * Corresponds to function at 0x1304.
 */
void leaf_function_b(TaintedData* data) {
    printf("leaf_function_b: value=%d, source=%s, taint=%d\n",
           data->value, data->source, data->taint_level);
    data->value *= 2;
}

/**
 * @brief Initializes a TaintedData structure from an external source string.
 * Corresponds to function at 0x11E9.
 */
void create_untrusted_data(TaintedData* data, const char* external_input) {
    data->value = 42;
    data->taint_level = 1; // Initial taint level for external data
    // The strncpy with 0x3F (63) is used to leave space for a null terminator.
    strncpy(data->source, external_input, sizeof(data->source) - 1);
    data->source[sizeof(data->source) - 1] = '\0'; // Ensure null termination
}

/**
 * @brief An intermediate processing step that calls two leaf functions.
 * Corresponds to function at 0x1353.
 * Note: The TaintedData is passed by value, creating a local copy.
 */
void intermediate_function(TaintedData* output_data, TaintedData input_data) {
    printf("intermediate_function received: source=%s, value=%d\n",
           input_data.source, input_data.value);
           
    leaf_function_a(&input_data);
    leaf_function_b(&input_data);
    
    // WARNING: This operation is unsafe if the buffer is nearly full.
    // This corresponds to: strcpy((char *)&s + strlen(...) + 4, "->intermediate");
    strcat(input_data.source, "->intermediate");
    
    // The modified local copy is written to the output pointer.
    *output_data = input_data;
}

/**
 * @brief Another intermediate processing step that calls one leaf function.
 * Corresponds to function at 0x141A.
 * Note: The TaintedData is passed by value, creating a local copy.
 */
void another_intermediate(TaintedData* output_data, TaintedData input_data) {
    printf("another_intermediate received: source=%s, value=%d\n",
           input_data.source, input_data.value);
           
    leaf_function_a(&input_data);
    
    // WARNING: This operation is unsafe if the buffer is nearly full.
    // This corresponds to: strcpy((char *)&s + strlen(...) + 4, "->another_intermediate");
    strcat(input_data.source, "->another_intermediate");
    
    // The modified local copy is written to the output pointer.
    *output_data = input_data;
}

/**
 * @brief Prints the final state of a TaintedData object.
 * Corresponds to function at 0x14E6.
 */
void process_result(const TaintedData* data) {
    puts("\n=== Final Result ===");
    printf("Value: %d\n", data->value);
    printf("Source: %s\n", data->source);
    printf("Taint Level: %d\n", data->taint_level);
}

/**
 * @brief Main program entry point.
 * Corresponds to function at 0x154D.
 */
int main(int argc, char* argv[]) {
    // Stack allocations corresponding to p_s, s_1, v28, and v33 in decompilation.
    TaintedData data1, data2;
    TaintedData result_path1, result_path2;

    puts("=== Program Start ===\n");

    // 1. Create two independent, tainted data objects.
    create_untrusted_data(&data1, "external_input_1");
    create_untrusted_data(&data2, "external_input_2");

    printf("Initial data1: source=%s, value=%d, taint=%d\n\n",
           data1.source, data1.value, data1.taint_level);

    // 2. Process the first data object through a series of functions.
    // The pass-by-value semantic from the assembly is preserved.
    intermediate_function(&result_path1, data1);
    printf("After intermediate_function: source=%s, value=%d\n\n",
           result_path1.source, result_path1.value);

    // 3. Process the second data object through a different function.
    another_intermediate(&result_path2, data2);
    printf("After another_intermediate: source=%s, value=%d\n\n",
           result_path2.source, result_path2.value);

    // 4. Merge the results from the two processing paths.
    result_path1.value += result_path2.value;
    
    // WARNING: These two `strcat` calls are the source of a critical
    // stack-based buffer overflow vulnerability. No bounds checking is performed.
    strcat(result_path1.source, "<-merged_from_");
    strcat(result_path1.source, result_path2.source);

    // 5. Display the final, merged result.
    process_result(&result_path1);

    puts("\n=== Program End ===");
    return 0;
}

Authoritative Justification of Reconstruction

  1. Central Data Structure (TaintedData): The entire program's logic revolves around a single, consistent data structure. Its layout was reverse-engineered from pointer arithmetic and typed memory accesses across multiple functions (*(_DWORD *)p_s, p_s + 4, *((_DWORD *)p_s + 17)), which directly map to the value, source, and taint_level fields, respectively. The 72-byte size aligns with the stack allocations observed in main.

  2. Function Signatures and Parameter Passing:

    • Functions like leaf_function_a and create_untrusted_data modify data in place, consistent with taking a pointer (TaintedData*).
    • The intermediate functions (intermediate_function, another_intermediate) were observed to receive a pointer to an output buffer (a1) and the full data structure on the stack (s). This is reconstructed as passing the output buffer by pointer and the input data by value, which creates a local copy for modification, exactly matching the assembly's behavior.
    • process_result only reads from the final structure, so it is reconstructed to take a const pointer for correctness and safety.
  3. Data Flow and Taint Propagation:

    • Taint Introduction: create_untrusted_data acts as the "taint source," initializing value to a constant 42 and taint_level to 1.
    • Taint Modification: leaf_function_a is the only function that modifies the taint level, incrementing it by one. This demonstrates explicit taint propagation.
    • Data Transformation: The leaf functions perform arithmetic operations (+= 10, *= 2), while the intermediate functions modify the source string to log the data's path through the call graph.
    • Data Merging: The main function demonstrates a taint-unaware merge. It correctly combines the numerical value fields (result_path1.value += result_path2.value;) but makes a critical error in merging the source strings. The taint_level of the second path is implicitly dropped, and only the level from the first path is preserved in the final result_path1 object.
  4. Vulnerability Reconstruction: The analysis identified high-impact buffer overflow risks. The reconstructed code uses strcat where the decompilation showed strcpy to a calculated offset. strcat is the functional C equivalent and makes the vulnerability clear. The comments explicitly flag these strcat calls in main as the source of a critical stack-based buffer overflow, which was a key finding of the data flow analysis. The combined length of the source strings from result_path1 and result_path2, plus the literal string, can easily exceed the 64-byte buffer capacity of result_path1.source, leading to stack corruption.

#include <stdio.h>
#include <string.h>
struct Data {
int value;
char source[64];
int taint_level;
};
// Source function - creates tainted data
struct Data create_untrusted_data(const char *origin) {
struct Data d;
d.value = 42;
d.taint_level = 1;
strncpy(d.source, origin, sizeof(d.source) - 1);
d.source[sizeof(d.source) - 1] = '\0';
return d;
}
// Leaf function - consumes and propagates data
void leaf_function_a(struct Data *data) {
printf("leaf_function_a: value=%d, source=%s, taint=%d\n",
data->value, data->source, data->taint_level);
data->value += 10;
data->taint_level++;
}
// Leaf function - consumes and propagates data
void leaf_function_b(struct Data *data) {
printf("leaf_function_b: value=%d, source=%s, taint=%d\n",
data->value, data->source, data->taint_level);
data->value *= 2;
}
// Intermediate function - transforms data
struct Data intermediate_function(struct Data input) {
printf("intermediate_function received: source=%s, value=%d\n",
input.source, input.value);
leaf_function_a(&input);
leaf_function_b(&input);
strcat(input.source, "->intermediate");
return input;
}
// Another intermediate - different transformation path
struct Data another_intermediate(struct Data input) {
printf("another_intermediate received: source=%s, value=%d\n",
input.source, input.value);
leaf_function_a(&input);
strcat(input.source, "->another_intermediate");
return input;
}
// Sink function - final consumer
void process_result(struct Data result) {
printf("\n=== Final Result ===\n");
printf("Value: %d\n", result.value);
printf("Source: %s\n", result.source);
printf("Taint Level: %d\n", result.taint_level);
}
int main(void) {
printf("=== Program Start ===\n\n");
// Create untrusted data with origin tracking
struct Data data1 = create_untrusted_data("external_input_1");
struct Data data2 = create_untrusted_data("external_input_2");
printf("Initial data1: source=%s, value=%d, taint=%d\n\n",
data1.source, data1.value, data1.taint_level);
// Pass through intermediate functions
struct Data result1 = intermediate_function(data1);
printf("After intermediate_function: source=%s, value=%d\n\n",
result1.source, result1.value);
struct Data result2 = another_intermediate(data2);
printf("After another_intermediate: source=%s, value=%d\n\n",
result2.source, result2.value);
// Merge data paths
result1.value += result2.value;
strcat(result1.source, "<-merged_from_");
strcat(result1.source, result2.source);
// Sink - final processing
process_result(result1);
printf("\n=== Program End ===\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment