Filtering The Loop For Single Page and Blog Page

As an example (adjust to suit your needs):

add_action('loop_start', function() {
   if ( is_single() || is_home() )
       echo '<div>';
});

add_action('loop_end', function() {
   if ( is_single() || is_home() )
       echo '</div>';
});

You may need to adjust the conditional statements further if you wish to target archive pages and the like — learn more about the template hierarchy here.

To understand these hooks further you should inspect the_post() and have_posts() methods within the WP_Query class in wp-includes/query.php.

But for your immediate pleasure…

loop_start hook:

/**
 * Fires once the loop is started.
 *
 * @since 2.0.0
 *
 * @param WP_Query &$this The WP_Query instance (passed by reference).
 */
do_action_ref_array( 'loop_start', array( &$this ) );

loop_end hook:

/**
 * Fires once the loop has ended.
 *
 * @since 2.0.0
 *
 * @param WP_Query &$this The WP_Query instance (passed by reference).
 */
do_action_ref_array( 'loop_end', array( &$this ) );